import { v4 as uuidv4 } from 'uuid';

import insertClipsToList from '../insertClipsToList';
import { getDerivedTiming } from '../selectors';
import { StudioClip, StudioProjectState } from '../types';

/**
 * Creates a state updater function that updates a specific clip within tracks.
 * This is a common pattern used throughout the codebase to update a clip's properties.
 *
 * @param clipId The ID of the clip to update
 * @param updateFn A function that receives the current clip and returns the updated clip
 * @returns A function that can be used with setState to update the clip
 */
export default function duplicateClip(
  clipId: string,
  updateFn: (clip: StudioClip) => StudioClip
) {
  return (state: StudioProjectState): StudioProjectState => ({
    ...state,
    metadata: {
      ...state.metadata,
      usedDuplicate: true,
    },
    tracks: state.tracks.map((track) => {
      const clip = track.clips.find((c) => c.id === clipId);
      if (!clip) return track;
      return {
        ...track,
        clips: insertClipsToList(
          getDerivedTiming(state),
          // the ID is not overwritten here - the updated clip by default behaves as though it is the original clip.
          // since the manipulated copy is likely the one that has the user's attention, we probably want it to retain any selection and focus references.
          // by keeping the ID the same, we have fewer other parts of the state to modify.
          [updateFn(clip)],
          track.clips.map((c) => (c.id === clipId ? { ...c, id: uuidv4() } : c)) // change the ID of the ACTUAL original clip.
        ),
      };
    }),
  });
}
