import { useEffect, useRef, useState } from 'react';
import localforage from 'localforage';
import { ProjectState, Selection, SendableProjectState } from '../types';
import { fromSendable, toSendable } from '../audio/utils/sandboxTools';
import audioContext from '../audio/utils/audioContext';
import getQueryParam from '../utils/getQueryParam';
import decodeAudio from '../audio/utils/decodeAudio';
import { expandedTrackHeight } from '../styles/dimensions';

export const AUTO_LOADER_STORAGE_KEY = 'project-state-feb-11-2021';

const linkableProjects = {
  drums: [[require('../demoProjects/GuitarBassDrums/ShortDrums.wav'), 'Drums']],
  speech: [[require('../demoProjects/Speech/Speech.wav'), 'Speech']]
} as {[key: string]: [string, string][]};

export default (saveAllowed: boolean, state: ProjectState, loadProjectState: (state: ProjectState, selection?: Selection) => void) => {
  const [hasLoadedInitialState, setHasLoadedInitialState] = useState(false);
  const hasLoadedInitialStateRef = useRef(false);

  useEffect(() => {
    if (!hasLoadedInitialStateRef.current) {
      localforage.getItem(AUTO_LOADER_STORAGE_KEY).then((result) => {
        if (result && (result as SendableProjectState).tracks.length > 0) {
          loadProjectState(fromSendable(result as SendableProjectState));
        } else {
          // load the project specified in the url
          const linkedProjectName = getQueryParam('audio');
          const linkedDemoProject = linkedProjectName && linkableProjects[linkedProjectName];
          if (!!linkedDemoProject) {
            Promise.all(linkedDemoProject.map(([url]) => decodeAudio(url))).then((buffers) => {
              loadProjectState(
                {
                  sampleRate: audioContext.sampleRate,
                  tracks: buffers.map((buffer, index) => ({
                    title: linkedDemoProject[index][1],
                    height: expandedTrackHeight,
                    audioBuffers: [buffer]
                  }))
                },
                [[0, Math.max(...buffers.map((b) => b.length))], buffers.map((_b, i) => i)]
              );
            });
          }
        }
        hasLoadedInitialStateRef.current = true;
        setHasLoadedInitialState(true);
      });
    }
  }, [loadProjectState, setHasLoadedInitialState]);

  const saveTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);

  useEffect(
    () => {
      if (saveAllowed && hasLoadedInitialStateRef.current) {
        if (saveTimeout.current) {
          clearTimeout(saveTimeout.current);
        }
        saveTimeout.current = setTimeout(
          () => {
            localforage.setItem(AUTO_LOADER_STORAGE_KEY, toSendable(state));
          },
          300
        );
      }
    },
    [state, saveAllowed]
  );

  return hasLoadedInitialState;
}
