import { StudioProjectState } from '../types';

export const DEFAULT_LOOP_DURATION_BEATS = 8;

export default function toggleTimelineLoop(
  startBeatsArg: number,
  endBeatsArg: number,
  enabledArg?: boolean
) {
  return (state: StudioProjectState) => {
    // If enabledArg is explicitly provided (e.g., from drag finishing), use args directly.
    if (enabledArg !== undefined) {
      let finalEndBeats = endBeatsArg;
      // Ensure loop has a duration if start and end are the same
      if (endBeatsArg === startBeatsArg) {
        finalEndBeats = startBeatsArg + DEFAULT_LOOP_DURATION_BEATS;
      }
      return {
        ...state,
        loop: {
          enabled: enabledArg,
          startBeats: startBeatsArg,
          endBeats: finalEndBeats,
        },
      };
    }

    // --- This is a TOGGLE operation (button press, enabledArg is undefined) ---
    let newStartBeats: number;
    let newEndBeats: number;
    const newEnabledState: boolean = !state.loop.enabled;

    if (newEnabledState) {
      // ---- Loop is being turned ON ----
      const hasActiveSelection =
        state.selection.anchorBeats !== state.selection.focusBeats;
      if (hasActiveSelection) {
        // Snap to current selection
        newStartBeats = Math.min(
          state.selection.anchorBeats,
          state.selection.focusBeats
        );
        newEndBeats = Math.max(
          state.selection.anchorBeats,
          state.selection.focusBeats
        );
      } else {
        // No active selection, use loop's last known position or default to cursor
        if (state.loop.startBeats === 0 && state.loop.endBeats === 0) {
          // Loop was never set or was at 0,0. Default to current cursor position.
          // state.selection.anchorBeats is the cursor position if no range is selected.
          newStartBeats = state.selection.anchorBeats;
          newEndBeats =
            state.selection.anchorBeats + DEFAULT_LOOP_DURATION_BEATS;
        } else {
          // Loop has a stored position (from when it was last active or set), reuse it.
          newStartBeats = state.loop.startBeats;
          newEndBeats = state.loop.endBeats;
        }
      }
    } else {
      // ---- Loop is being turned OFF ----
      // Preserve its current position in state.loop for next time it's enabled without selection
      newStartBeats = state.loop.startBeats;
      newEndBeats = state.loop.endBeats;
    }

    // Ensure loop always has a minimum duration if start and end are the same after logic above
    if (newEndBeats === newStartBeats) {
      newEndBeats = newStartBeats + DEFAULT_LOOP_DURATION_BEATS;
    }

    return {
      ...state,
      loop: {
        enabled: newEnabledState,
        startBeats: newStartBeats,
        endBeats: newEndBeats,
      },
    };
  };
}
