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

/**
 * Creates a state updater function that updates a list of tracks and take lanes within the project state.
 * This is a common pattern used throughout the codebase to update a track's properties.
 *
 * @param trackIds The IDs of the tracks and take lanes to update
 * @param updateFn A function that receives a current track and returns an updated track
 * @returns A function that can be used with setState to update the track
 */
export default function updateTracksAndTakeLanes(
  trackIds: string[],
  updateFn: <T extends StudioTrackCore>(track: T) => T
) {
  return (state: StudioProjectState): StudioProjectState => ({
    ...state,
    tracks: state.tracks.map((track) => {
      let newTrack = trackIds.includes(track.id) ? updateFn(track) : track;
      if (
        newTrack.takeLanes.some((takeLane) => trackIds.includes(takeLane.id))
      ) {
        newTrack = {
          ...newTrack,
          takeLanes: newTrack.takeLanes.map((takeLane) =>
            trackIds.includes(takeLane.id) ? updateFn(takeLane) : takeLane
          ),
        };
      }
      return newTrack;
    }),
  });
}

export const updateSelectedTracksAndTakeLanes =
  (updateFn: <T extends StudioTrackCore>(track: T) => T) =>
  (state: StudioProjectState): StudioProjectState =>
    updateTracksAndTakeLanes(state.selection.trackIds, updateFn)(state);

export const updateTrackOrTakeLane = (
  trackId: string,
  updateFn: <T extends StudioTrackCore>(track: T) => T
) => {
  return updateTracksAndTakeLanes([trackId], updateFn);
};
