import { v4 as uuidv4 } from 'uuid';

import { StudioProjectState } from './types';

const EPSILON = 0.000001; // ~0.1 samples at 120bpm
// sort clips and clip creation intents by startBeats
export default function cleanState<T extends StudioProjectState>(state: T): T {
  if ((state.tracks as any).includes(undefined)) {
    console.error('Found undefined track in state!!!');
    state.tracks = state.tracks.filter((t) => t !== undefined);
  }
  state.tracks.forEach((track) => {
    for (let i = track.clips.length - 1; i >= 0; i--) {
      if (
        Math.abs(track.clips[i].startBeats - track.clips[i].endBeats) < EPSILON
      ) {
        track.clips.splice(i, 1);
      } else if (
        track.clips[i - 1] &&
        track.clips[i].startBeats < track.clips[i - 1].endBeats
      ) {
        track.clips[i - 1] = {
          ...track.clips[i - 1],
          endBeats: track.clips[i].startBeats,
        };
      }
    }
    track.clips.sort((a, b) => a.startBeats - b.startBeats);
    if (track.clips.some((c) => c.endBeats <= c.startBeats)) {
      track.clips = track.clips.filter((c) => c.endBeats > c.startBeats);
    }
    const usedIds: Record<string, boolean> = {};
    track.clips.forEach((c) => {
      if (usedIds[c.id]) {
        console.error('Fixed duplicate clip id:', c.id);
        console.trace();
        c.id = uuidv4();
      }
      usedIds[c.id] = true;
    });
    track.clipCreationIntents.sort((a, b) => {
      let diff = (a.startBeats ?? -Infinity) - (b.startBeats ?? -Infinity);
      if (diff === 0) {
        diff = (a.endBeats ?? -Infinity) - (b.endBeats ?? -Infinity);
      }
      return diff;
    });
  });

  return state;
}
