import moveTrackContentAfter from '../actionHelpers/moveTrackContentAfter';
import { OverlapType, getOverlapType } from '../getOverlapType';
import {
  getDerivedTiming,
  getSelectionEndBeats,
  getSelectionStartBeats,
} from '../selectors';
import { StudioProjectState } from '../types';

export default function closeUnselectedGaps(state: StudioProjectState) {
  const result: StudioProjectState = {
    ...state,
    tracks: [],
  };
  let didSomething = false;

  for (const track of state.tracks) {
    let newTrack = track;
    const selectionInTrack =
      state.selection.focusedTrackId === track.id
        ? {
            startBeats: getSelectionStartBeats(state),
            endBeats: getSelectionEndBeats(state),
          }
        : {
            startBeats: -Infinity,
            endBeats: -Infinity,
          };

    for (let i = 0; i < newTrack.clips.length; i++) {
      const clip = newTrack.clips[i];

      const nextClip = newTrack.clips[i + 1];
      if (
        nextClip &&
        nextClip.startBeats > clip.endBeats &&
        getOverlapType(
          clip.endBeats,
          nextClip.startBeats,
          selectionInTrack.startBeats,
          selectionInTrack.endBeats
        ) === OverlapType.NoOverlap &&
        !track.clipCreationIntents.some(
          (c) =>
            getOverlapType(
              clip.endBeats,
              nextClip.startBeats,
              c.startBeats ?? -Infinity,
              c.endBeats ?? Infinity
            ) !== OverlapType.NoOverlap
        )
      ) {
        const delta = nextClip.startBeats - clip.endBeats;
        newTrack = moveTrackContentAfter(
          getDerivedTiming(state),
          newTrack,
          clip.endBeats,
          -delta
        );
        didSomething = true;
        if (state.selection.focusedTrackId === track.id) {
          if (result.selection.anchorBeats > clip.endBeats) {
            result.selection = {
              ...result.selection,
              anchorBeats: result.selection.anchorBeats - delta,
            };
          }

          if (result.selection.focusBeats > clip.endBeats) {
            result.selection = {
              ...result.selection,
              focusBeats: result.selection.focusBeats - delta,
            };
          }
        }
      }
    }

    result.tracks.push(newTrack);
  }

  if (!didSomething) {
    return state;
  }

  return result;
}
