import { createContext, useCallback, useEffect, useMemo, useState } from 'react';
import api from '../api';
import { StoredCommand } from '../types';
import getQueryParam from '../utils/getQueryParam';
import useStorageBackedState from './useStorageBackedState';
import click from '../audio/commands/generators/click';
import tone from '../audio/commands/generators/tone';
import nudgeLeft from '../audio/commands/projectCommands/nudgeLeft';
import nudgeRight from '../audio/commands/projectCommands/nudgeRight';
import deleteEdit from '../audio/commands/simpleAudioCommands/deleteEdit';
import fadeIn from '../audio/commands/simpleAudioCommands/fadeIn';
import fadeOut from '../audio/commands/simpleAudioCommands/fadeOut';
import gain from '../audio/commands/simpleAudioCommands/gain';
import ghost from '../audio/commands/simpleAudioCommands/ghost';
import meanFilter from '../audio/commands/simpleAudioCommands/meanFilter';
import simpleCompressor from '../audio/commands/simpleAudioCommands/simpleCompressor';
import timeTravelDelay from '../audio/commands/simpleAudioCommands/timeTravelDelay';


const favouriteCommands = [
  ghost,
  meanFilter,
  tone,
  simpleCompressor,
];

const essentialCommands = [
  fadeIn,
  fadeOut,
  deleteEdit,
  nudgeLeft,
  nudgeRight,
];

const starterCommands = [
  gain,
  timeTravelDelay,
  click,
];

const RECENT_COMMANDS_STORAGE_KEY = 'feb-16-2021-library-recent-commands';

const linkedCommandId = getQueryParam('code');

export const useCommandLibrary = () => {
  const [communityCommandList, setCommunityCommandList] = useState<StoredCommand[]>([]);
  const [hasFetchedList, setHasFetchedList] = useState(false);
  const [recentCommands, setRecentCommands] = useStorageBackedState<StoredCommand[]>([], RECENT_COMMANDS_STORAGE_KEY);
  const commands = useMemo(() => ({
    starter: starterCommands,
    essentials: essentialCommands,
    favourites: favouriteCommands,
    community: communityCommandList,
    recent: recentCommands
  }), [communityCommandList, recentCommands]);

  const allCommands = useMemo(() => {
    return Object.values(commands).reduce((a, c) => [...a, ...c], []);
  }, [commands]);

  const linkedCommand = useMemo(() => {
    return allCommands.find(({ id }) => String(id) === linkedCommandId);
  }, [allCommands]);

  useEffect(() => {
    if (!hasFetchedList) {
      setHasFetchedList(true);
      api.list().then((result) => {
        setCommunityCommandList(result.commands);
      });
    }
  }, [hasFetchedList, communityCommandList, setCommunityCommandList]);

  const onOpenCommand = useCallback(
    (command: StoredCommand) => {
      const newRecentCommands = [command, ...recentCommands.filter((c) => c.id !== command.id)].slice(0, 6);
      setRecentCommands(newRecentCommands);
    },
    [setRecentCommands, recentCommands]
  );

  return {
    onOpenCommand,
    linkedCommand,
    commands
  };
}

export const CommandLibraryContext = createContext<ReturnType<typeof useCommandLibrary>>(undefined as never);
