import {json} from "@remix-run/node";
import {useEffect, useState} from 'react';
import {useOutletContext, useParams} from 'react-router-dom';

import AssetsContext from '@/context/assets.js';
import ClientContext from '@/context/client.js';
import DebugContext from '@/context/debug.js';
import EcsContext from '@/context/ecs.js';
import MainEntityContext from '@/context/main-entity.js';
import Ui from '@/react-components/ui.jsx';
import {juggleSession} from '@/session.server';

export async function loader({request}) {
  await juggleSession(request);
  return json({});
}

export default function PlaySpecific() {
  const Client = useOutletContext();
  const assetsTuple = useState({});
  const [client, setClient] = useState();
  const mainEntityTuple = useState();
  const setMainEntity = mainEntityTuple[1];
  const debugTuple = useState(false);
  const ecsTuple = useState();
  const [disconnected, setDisconnected] = useState(false);
  const params = useParams();
  const [type, url] = params['*'].split('/');
  useEffect(() => {
    if (!Client) {
      return;
    }
    const client = new Client();
    async function connect() {
      await client.connect(url);
      setClient(client);
    }
    connect();
    return () => {
      client.disconnect();
    };
  }, [Client, url]);
  // Sneakily use beforeunload to snag some time to save.
  useEffect(() => {
    if ('local' !== type) {
      return;
    }
    async function onBeforeUnload() {
      client.disconnect();
      function waitForSave() {
        return new Promise((resolve) => setTimeout(resolve, 0));
      }
      while (client.worker) { await waitForSave(); }
    }
    addEventListener('beforeunload', onBeforeUnload);
    return () => {
      removeEventListener('beforeunload', onBeforeUnload);
    };
  });
  useEffect(() => {
    if (!client) {
      return;
    }
    function onConnectionStatus(status) {
      switch (status) {
        case 'aborted': {
          setDisconnected(true);
          break;
        }
        case 'connected': {
          setDisconnected(false);
          break;
        }
      }
    }
    client.addPacketListener('ConnectionStatus', onConnectionStatus);
    return () => {
      client.removePacketListener('ConnectionStatus', onConnectionStatus);
    };
  }, [client]);
  useEffect(() => {
    if (!client || !disconnected) {
      return;
    }
    setMainEntity(undefined);
    async function reconnect() {
      await client.connect(url);
    }
    reconnect();
    const handle = setInterval(reconnect, 1000);
    return () => {
      clearInterval(handle);
    };
  }, [client, disconnected, setMainEntity, url]);
  // useEffect(() => {
  //   let source = true;
  //   async function play() {
  //     const ctx = new AudioContext();
  //     const response = await fetch(new URL('/assets/yuff.wav', window.location.origin));
  //     const buffer = await ctx.decodeAudioData(await response.arrayBuffer());
  //     if (!source) {
  //       return;
  //     }
  //     source = ctx.createBufferSource();
  //     source.buffer = buffer;
  //     source.connect(ctx.destination);
  //     source.loop = true;
  //     source.start();
  //   }
  //   setTimeout(play, 1000);
  //   return () => {
  //     if (true !== source) {
  //       source.stop();
  //     }
  //     source = false;
  //   };
  // }, [])
  return (
    <ClientContext.Provider value={client}>
      <MainEntityContext.Provider value={mainEntityTuple}>
        <EcsContext.Provider value={ecsTuple}>
          <DebugContext.Provider value={debugTuple}>
            <AssetsContext.Provider value={assetsTuple}>
              <Ui disconnected={disconnected} />
            </AssetsContext.Provider>
          </DebugContext.Provider>
        </EcsContext.Provider>
      </MainEntityContext.Provider>
    </ClientContext.Provider>
  );
}
