import { areMarkersEqual } from '@suno/studiokit/projectState/warpMarkersRegistry';
import { getWarpEnabledAndPopulated } from '@suno/studiokit/warpUtils';
import { memoize } from 'lodash-es';
import { v4 as uuidv4 } from 'uuid';

import { StudioClip } from './types';

const clipListIds = new Map<StudioClip[], string>();

export const areClipsContentAligned = (
  clipA: StudioClip,
  clipB: StudioClip
) => {
  return (
    clipA.clipId === clipB.clipId &&
    getWarpEnabledAndPopulated(clipA.warp) ===
      getWarpEnabledAndPopulated(clipB.warp) &&
    clipA.warp.speed === clipB.warp.speed &&
    clipA.transposition === clipB.transposition &&
    clipA.amplitude === clipB.amplitude &&
    clipA.mute === clipB.mute &&
    areMarkersEqual(clipA.warp.markers, clipB.warp.markers) &&
    Math.abs(
      clipB.startBeats -
        clipA.startBeats -
        (clipB.readStartBeats - clipA.readStartBeats)
    ) < 0.00001
  );
};

export default memoize(
  function reduceClips(clips: StudioClip[]): StudioClip[] {
    const result: StudioClip[] = [];
    let currentClip: StudioClip | null = null;
    for (const clip of clips) {
      if (
        currentClip &&
        areClipsContentAligned(currentClip, clip) &&
        currentClip.endBeats === clip.startBeats &&
        getWarpEnabledAndPopulated(currentClip.warp)
      ) {
        currentClip.endBeats = clip.endBeats;
      } else if (currentClip) {
        result.push(currentClip);
        currentClip = { ...clip };
      } else {
        currentClip = { ...clip };
      }
    }
    if (currentClip) {
      result.push(currentClip);
    }
    return result.sort((a, b) => a.startBeats - b.startBeats);
  },
  (arg) => {
    if (clipListIds.has(arg)) {
      return clipListIds.get(arg);
    }
    const id = uuidv4();
    if (clipListIds.size >= 250) {
      clipListIds.delete(Array.from(clipListIds.keys())[0]!);
    }
    clipListIds.set(arg, id);
    return id;
  }
);
