import { Track } from '../types';
import { createContext, useCallback, useMemo } from 'react';
import useTimelineEdits from './useTimelineEdits';
import useAudioRecorder from './useAudioRecorder';
import useProjectHistory from './useProjectHistory';

export const useProject = (sampleRate: number) => {
  const { state, selection, selectionInteractions, undo, redo, pushProjectState, alterProjectState, loadProjectState } = useProjectHistory({ sampleRate, tracks: [] });
  const timelineInteractions = useTimelineEdits(state, selection, pushProjectState, alterProjectState);
  const recorder = useAudioRecorder(sampleRate, timelineInteractions.receiveRecording);

  const alterTrack = useCallback(
    (trackIndex: number, alterFunction: (track: Track) => Track) => {
      alterProjectState(
        {
          ...state,
          tracks: state.tracks.map((t, i) => i === trackIndex ? alterFunction(t) : t)
        },
        selection
      );
    },
    [alterProjectState, state, selection]
  );

  const rename = useCallback(
    (trackIndex: number, newTitle: string) => alterTrack(trackIndex, (t) => ({ ...t, title: newTitle })),
    [alterTrack]
  );

  const resize = useCallback(
    (trackIndex: number, newHeight: number) => alterTrack(trackIndex, (t) => ({ ...t, height: newHeight })),
    [alterTrack]
  );

  const deleteTrack = useCallback(
    (trackIndex: number) => {
      pushProjectState(
        {
          ...state,
          tracks: state.tracks.filter((t, i) => i !== trackIndex)
        },
        selection
      );
    },
    [state, selection, pushProjectState]
  );

  const interactions = useMemo(
    () => ({
      selection: selectionInteractions,

      track: {
        rename,
        resize,
        deleteTrack
      },

      undo,
      redo,

      timelineContent: timelineInteractions
    }),
    [
      selectionInteractions,

      rename,
      resize,
      deleteTrack,

      undo,
      redo,

      timelineInteractions
    ]
  );

  return useMemo(
    () => ({ state, selection, interactions, recorder, loadProjectState }),
    [state, selection, interactions, recorder, loadProjectState]
  );
}

export const ProjectContext = createContext<ReturnType<typeof useProject>>(undefined as never);
