<script lang="ts">
  /**
   * Settings — mostly the layout editor, which is the feature this whole app
   * exists to have.
   *
   * Two things are editable: the CSS applied to *your* view of plspace (stored
   * locally), and whether the CSS other people publish on their profiles is
   * honoured when you visit them.
   */
  import { useAppServices } from '$lib/app-services'
  import { CSS_FIELD_NAMES, PROFILE_SCOPE } from '$lib/stores/theme.svelte'
  import { PRESETS, EXAMPLE_CSS } from '$lib/themes'
  import { instanceDomain } from '$lib/api/endpoints'
  import { displayNameOf, profilePath } from '$lib/util/profile'
  import Module from '$components/common/Module.svelte'
  import PublicProfileEditor from '$components/profile/PublicProfileEditor.svelte'
  import PublishedCssEditor from '$components/profile/PublishedCssEditor.svelte'

  const { session, theme } = useAppServices()

  let draft = $state(theme.viewerCss)
  let saved = $state(false)

  const domain = $derived(session.host ? instanceDomain(session.instance, session.host) : '')

  /** Class hooks worth documenting, grouped the way pages are built. */
  const HOOKS: Array<{ group: string; entries: Array<[string, string]> }> = [
    {
      group: 'Page skeletons',
      entries: [
        ['.page', 'Every page’s outer container'],
        ['.profile-page', 'The profile page — also the scope for published profile CSS'],
        ['.layout--split', 'Two-column pages (left rail + main)'],
        ['.layout--dashboard', 'The three-column home page'],
        ['.layout-column--left / --main / --right', 'The individual columns'],
      ],
    },
    {
      group: 'Boxes',
      entries: [
        ['.module', 'A bordered box'],
        ['.module-header', 'Its caption bar'],
        ['.module-body', 'Its contents'],
        ['.module--band', 'The peach-bar variant used in the main column'],
        ['.section-heading', '“About me:” style orange headings'],
        ['.notification-toast-stack, .notification-toast', 'Background notification toasts'],
      ],
    },
    {
      group: 'Profile',
      entries: [
        ['.profile-photo', 'The big photo'],
        ['.profile-headline', 'The quoted line beside it'],
        ['.profile-vitals', 'Gender / age / location / last active'],
        ['.interests-table, .interests-label, .interests-value', 'The Interests table'],
        ['.friend-grid, .friend-card, .friend-card-photo', 'Friend Space'],
        ['.pic-stream, .pic-card, .pic-card-image', 'Pics stream'],
      ],
    },
    {
      group: 'Blog entries',
      entries: [
        ['.blog-entry', 'One entry'],
        ['.blog-entry[data-mine="true"]', 'Entries you wrote'],
        ['.blog-entry[data-visibility="private"]', 'Friends-only entries'],
        ['.blog-entry[data-boosted="true"]', 'Reposts'],
        ['.youtube-attachment, .youtube-embed', 'YouTube embeds'],
        ['.blog-action[aria-pressed="true"]', 'Kudos/Repost buttons you’ve activated'],
        ['.comment[data-depth="2"]', 'Comments by nesting depth'],
      ],
    },
  ]

  function save(): void {
    theme.setViewerCss(draft)
    saved = true
    setTimeout(() => (saved = false), 2000)
  }

  function applyPreset(css: string): void {
    draft = css
    theme.setViewerCss(css)
  }

  function reset(): void {
    draft = ''
    theme.setViewerCss('')
  }
</script>

<div class="page settings-page">
  <h1 class="page-title">Settings</h1>
  <p class="page-subtitle">Edit your public profile and customise how plspace looks.</p>

  <div class="layout--single">
    <Module title="Your account">
      {#if session.signedIn && session.me}
        <p>
          Signed in as
          <a href={profilePath(session.me)}>{displayNameOf(session.me)}</a>
          on <strong>{domain}</strong>.
        </p>
        <p class="field-row">
          <button type="button" class="button" onclick={() => void session.logout()}>Sign out</button>
          <button type="button" class="button" onclick={() => session.disconnect()}>
            Forget this server
          </button>
        </p>
      {:else if session.host}
        <p>Browsing <strong>{domain}</strong> as a guest.</p>
        <p class="field-row">
          <a class="button button--primary" href="#/login">Sign in</a>
          <button type="button" class="button" onclick={() => session.disconnect()}>
            Choose a different server
          </button>
        </p>
      {:else}
        <p>Not connected to a server. <a href="#/login">Choose one</a>.</p>
      {/if}
    </Module>

    <Module title="Your public profile" variant="band">
      <PublicProfileEditor />
    </Module>

    <Module title="Pick a layout" variant="band">
      <ul class="preset-list">
        {#each PRESETS as preset (preset.id)}
          <li class="preset">
            <button type="button" class="button preset-button" onclick={() => applyPreset(preset.css)}>
              {preset.name}
            </button>
            <span class="preset-description muted">{preset.description}</span>
          </li>
        {/each}
      </ul>
    </Module>

    <Module title="CSS for this browser only" variant="band">
      <p class="notice">
        <strong>Private viewing setting:</strong>
        this changes how plspace looks only for you, in this browser. It does not update your
        profile, and nobody else can see it.
      </p>
      <p>
        Overriding the custom properties in <code>styles/tokens.css</code> retints the entire app;
        the class hooks below let you go further.
      </p>

      <label class="visually-hidden" for="viewer-css">Your CSS</label>
      <textarea
        id="viewer-css"
        class="css-editor"
        bind:value={draft}
        rows="14"
        spellcheck="false"
        placeholder={EXAMPLE_CSS}
      ></textarea>

      <div class="field-row">
        <button type="button" class="button button--primary" onclick={save}>Save CSS</button>
        <button type="button" class="button" onclick={reset}>Reset to default</button>
        <button type="button" class="button" onclick={() => (draft = EXAMPLE_CSS)}>
          Load the example
        </button>
        {#if saved}<span class="muted">Saved.</span>{/if}
      </div>

      <p class="field-hint">
        <code>@import</code> and non-HTTPS <code>url()</code> values are stripped before your CSS is
        applied.
      </p>
    </Module>

    <Module title="Other people's layouts" variant="band">
      <label class="checkbox-field">
        <input
          type="checkbox"
          checked={theme.allowProfileCss}
          onchange={(event) => theme.setAllowProfileCss(event.currentTarget.checked)}
        />
        <span>
          Show profile layouts published by the people I visit
        </span>
      </label>
      <p class="field-hint">
        plspace publishes layouts in ordered fields named <code>plspace:css1</code>,
        <code>plspace:css2</code>, and so on. Legacy
        {#each CSS_FIELD_NAMES as name, index (name)}<code>{name}</code>{#if index < CSS_FIELD_NAMES.length - 1}, {/if}{/each}
        fields are still understood.
        Their rules are rewritten to apply only inside <code>{PROFILE_SCOPE}</code>, so a profile
        can restyle its own page but not the rest of plspace.
      </p>
    </Module>

    <Module title="CSS published on your profile" variant="band">
      <p>
        This editor writes the layout into profile fields on
        <strong>{domain || 'your server'}</strong>. Anyone who visits your profile with plspace
        will receive it automatically.
      </p>
      <PublishedCssEditor />
    </Module>

    <Module title="Class reference" variant="band">
      {#each HOOKS as section (section.group)}
        <h3 class="section-heading">{section.group}</h3>
        <table class="data-table hooks-table">
          <tbody>
            {#each section.entries as [selector, description] (selector)}
              <tr>
                <th class="data-table-label" scope="row"><code>{selector}</code></th>
                <td class="data-table-value">{description}</td>
              </tr>
            {/each}
          </tbody>
        </table>
      {/each}
    </Module>
  </div>
</div>
