<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 ConversationList from '$lib/components/ConversationList.svelte';
  import CreateConversationForm from '$lib/components/CreateConversationForm.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 conversationId = $derived(page.params.conversation);

  let conversations = $derived(session.conversations);

  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();
    }
  });

  // Automatically migrate last-active-channel info now that we call them "conversations."
  const STORE_KEY_LAST_ACTIVE = 'pilcrow:lastActiveConversation';
  const STORE_KEY_LAST_ACTIVE_CHANNEL = 'pilcrow:lastActiveChannel';

  function getLastActiveConversation() {
    const stored =
      localStorage.getItem(STORE_KEY_LAST_ACTIVE) ??
      localStorage.getItem(STORE_KEY_LAST_ACTIVE_CHANNEL);
    return JSON.parse(stored);
  }

  function setLastActiveConversation(conversationId) {
    localStorage.setItem(STORE_KEY_LAST_ACTIVE, JSON.stringify(conversationId));
    // Once we've saved to the new key, we no longer need the old one. Clean it up.
    localStorage.removeItem(STORE_KEY_LAST_ACTIVE_CHANNEL);
  }

  afterNavigate(() => {
    const conversationId = getLastActiveConversation();
    const inRoot = page.url.pathname === '/';
    if (inRoot && conversationId) {
      goto(`/c/${conversationId}`);
    } else if (conversationId) {
      setLastActiveConversation(conversationId || null);
    }
  });

  async function createConversation(name) {
    outbox.createConversation(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}>
    <ConversationList active={conversationId} {conversations} />
    <CreateConversationForm {createConversation} />
  </nav>
  <main>
    {@render children?.()}
  </main>
</div>
