<script>
  import { getContext, onDestroy, onMount } from 'svelte';

  import { browser } from '$app/environment';
  import { goto, afterNavigate } from '$app/navigation';
  import { page } from '$app/state';

  import TinyGesture from 'tinygesture';

  import * as api from '$lib/apiServer.js';
  import ChannelList from '$lib/components/ChannelList.svelte';
  import CreateChannelForm from '$lib/components/CreateChannelForm.svelte';

  let gesture = null;

  const { data, children } = $props();
  const { session, outbox } = data;

  onMount(session.begin.bind(session));
  onDestroy(session.end.bind(session));

  let pageContext = getContext('page');
  let channel = $derived(page.params.channel);

  let rawChannels = $derived(session.channels);
  let rawChannelsMeta = $derived(session.local.all);
  let rawMessages = $derived(session.messages);

  function enrichChannels(channels, channelsMeta, messages) {
    const enrichedChannels = [];
    for (const ch of channels.values()) {
      const channelMessages = messages.filter((message) => message.channel === ch.id);
      const lastMessage = channelMessages.slice(-1)[0];
      const lastMessageAt = lastMessage?.at;
      const lastReadAt = channelsMeta.get(ch.id)?.lastReadAt;
      const hasUnreads = lastReadAt === undefined || lastMessageAt > lastReadAt;
      enrichedChannels.push({
        ...ch,
        hasUnreads
      });
    }
    return enrichedChannels;
  }

  const enrichedChannels = $derived(enrichChannels(rawChannels, rawChannelsMeta, rawMessages));

  function setUpGestures() {
    if (!browser) {
      // Meaningless if we're not in a browser, so...
      return;
    }
    gesture = new TinyGesture(window);
    gesture.on('swiperight', () => {
      pageContext.showMenu = true;
    });
    gesture.on('swipeleft', () => {
      pageContext.showMenu = false;
    });
  }

  onMount(setUpGestures);

  onDestroy(async () => {
    if (gesture !== null) {
      gesture.destroy();
    }
  });

  const STORE_KEY_LAST_ACTIVE = 'pilcrow:lastActiveChannel';

  function getLastActiveChannel() {
    return browser && JSON.parse(localStorage.getItem(STORE_KEY_LAST_ACTIVE));
  }

  function setLastActiveChannel(channelId) {
    browser && localStorage.setItem(STORE_KEY_LAST_ACTIVE, JSON.stringify(channelId));
  }

  afterNavigate(() => {
    const lastActiveChannel = getLastActiveChannel();
    const inRoot = page.url.pathname === '/';
    if (inRoot && lastActiveChannel) {
      goto(`/ch/${lastActiveChannel}`);
    } else if (channel) {
      setLastActiveChannel(channel || null);
    }
  });

  async function createChannel(name) {
    await api.createChannel(name);
  }

  function onbeforeunload(event) {
    if (outbox.pending.length > 0) {
      // Prompt the user that they have unsaved (unsent) messages that may be lost.
      event.preventDefault();
    }
  }
</script>

<!--
  In theory, we [should be][bfcache-why] using an ephemeral event handler for this, rather than
  leaving it hooked up at all times. Some browsers decide whether a page is eligible for
  back/forward caching based on whether it has a beforeunload handler (among other factors), and
  having the event handler registered can slow down navigation on those browsers by forcing a
  network reload when the page could have been restored from memory.

  Most browsers _apparently_ no longer use that criterion, but I would have been inclined to follow
  the advice regardless as I don't feel up to the task of cataloguing which browsers it applies to.
  Unfortunately, it wouldn't matter if we did: SvelteKit itself registers beforeunload handlers, so
  (at least as of this writing) any work we do to try to dynamically register or unregister
  beforeunload handlers dynamically state would be wasted effort.

  For posterity, though, the appropriate code for doing so based on outbox state looks like

      $effect(() => {
        if (outbox.pending.length > 0) {
          window.addEventListener('beforeunload', onbeforeunload);
        }

        return () => {
          window.removeEventListener('beforeunload', onbeforeunload);
        };
      });

  [bfcache-why]: https://web.dev/articles/bfcache#beforeunload-caution
-->
<svelte:window {onbeforeunload} />

<svelte:head>
  <!-- TODO: unread count? -->
  <title>pilcrow</title>
</svelte:head>

<div id="interface">
  <nav id="sidebar" data-expanded={pageContext.showMenu}>
    <ChannelList active={channel} channels={enrichedChannels} />
    <div class="create-channel">
      <CreateChannelForm {createChannel} />
    </div>
  </nav>
  <main>
    {@render children?.()}
  </main>
</div>
