import { useMemo, useState, useCallback, useRef } from 'react';
import { trackInnerPadding } from '../styles/dimensions';
import { scaleByFactor, showBounds, showPoint } from '../components/Timeline/calculator';
import { createContext } from 'react';

export const useTimelineViewController = (projectDuration: number, viewportWidth: number) => {
  const fastStateRef = useRef({ samplesPerPx: 100, scrollLeft: 0 });

  const setSamplesPerPxAndScrollLeft = useCallback(
    ([samplesPerPx, scrollLeft]) => {
      fastStateRef.current.samplesPerPx = samplesPerPx;
      fastStateRef.current.scrollLeft = scrollLeft;
    },
    []
  );

  const setScrollLeft = useCallback(
    (newScrollLeft: number) => fastStateRef.current.scrollLeft = newScrollLeft,
    []
  );

  const [follow, setFollow] = useState(true);

  const state = useMemo(() => ({
    follow,
    viewportWidth,
    padding: trackInnerPadding,
    duration: projectDuration
  }), [
    follow,
    viewportWidth,
    projectDuration
  ]);

  const getCombinedState = useCallback(
    () => ({ ...state, ...fastStateRef.current }),
    [state]
  );

  const zoomOut = useCallback(
    () => {
      const state = getCombinedState();
      const newState = scaleByFactor(state, 0.9);
      setSamplesPerPxAndScrollLeft([newState.samplesPerPx, newState.scrollLeft]);
    },
    [setSamplesPerPxAndScrollLeft, getCombinedState]
  );

  const zoomIn = useCallback(
    () => {
      const state = getCombinedState();
      const newState = scaleByFactor(state, 1/0.9);
      setSamplesPerPxAndScrollLeft([newState.samplesPerPx, newState.scrollLeft]);
    },
    [setSamplesPerPxAndScrollLeft, getCombinedState]
  );

  const showAll = useCallback(
    () => {
      const state = getCombinedState();
      const newState = showBounds(state, 0, state.duration);
      setSamplesPerPxAndScrollLeft([newState.samplesPerPx, newState.scrollLeft]);
    },
    [setSamplesPerPxAndScrollLeft, getCombinedState]
  );

  const runShowPoint = useCallback(
    (point: number) => {
      const state = getCombinedState();
      setScrollLeft(showPoint(state, point).scrollLeft)
    },
    [setScrollLeft, getCombinedState]
  );

  return {
    state,
    fastStateRef,
    getCombinedState,
    interactions: {
      setScrollLeft,
      setFollow,

      zoomIn,
      zoomOut,
      showAll,
      showPoint: runShowPoint
    }
  }
}

export const TimelineViewControllerContext = createContext<ReturnType<typeof useTimelineViewController>>(undefined as never);
