import { SetStateAction } from 'react';

import { getDerivedTiming, getFallbackBPS } from '../selectors';
import { StudioProjectState, StudioTiming } from '../types';

export const MIN_BPM = 10;
export const MAX_BPM = 999;
export const MIN_BPS = MIN_BPM / 60;
export const MAX_BPS = MAX_BPM / 60;

export const activateManualTiming =
  (bps?: number) =>
  (state: StudioProjectState): StudioProjectState => {
    if (state.timing.type === 'manual' && state.timing.bps === bps) {
      return state;
    }

    const derivedTiming = getDerivedTiming(state);
    return {
      ...state,
      timing: {
        type: 'manual',
        ...derivedTiming,
        bps: Math.max(0.25, Math.min(12, bps ?? derivedTiming.bps)),
        lockBPS: true,
      },
    };
  };

export const activateFollowTrackTiming =
  (trackId?: string) =>
  (state: StudioProjectState): StudioProjectState => {
    trackId ||= state.tracks[0]?.id;

    if (!trackId) {
      return state;
    }

    if (
      state.timing.type === 'follow-track' &&
      state.timing.trackId === trackId
    ) {
      return state;
    }

    const fallbackBPS = getFallbackBPS(state);

    return {
      ...state,
      timing: {
        type: 'follow-track',
        trackId,
        fallbackBPS,
      },
    };
  };

export default function setTiming(timing: SetStateAction<StudioTiming>) {
  return (state: StudioProjectState) => {
    if (timing instanceof Function) {
      return {
        ...state,
        timing: timing(state.timing),
      };
    } else {
      return {
        ...state,
        timing,
      };
    }
  };
}
