const LEGACY_TRACKS = [
  ['scene', 'Scene 1', 'sceneSegments'],
  ['shader', 'Shader 1', 'shaderSegments'],
  ['media', 'Media 1', 'imageSegments'],
  ['postfx', 'Post FX 1', 'postfxSegments'],
];

export const CURRENT_PROJECT_VERSION = 13;

export function segmentsForType(tracks, type) {
  return tracks
    .filter(track => track.type === type)
    .sort((left, right) => left.order - right.order)
    .flatMap(track => (track.segments || []).map((segment, index) => ({
      ...segment,
      _trackId: track.id,
      _segIndex: index,
    })));
}

export function serializeExposedParams(exposedParams) {
  return Object.fromEntries(
    Object.entries(exposedParams || {}).map(([segmentId, params]) => [
      segmentId,
      params instanceof Set ? [...params] : params,
    ]),
  );
}

export function deserializeExposedParams(exposedParams) {
  return Object.fromEntries(
    Object.entries(exposedParams || {}).map(([segmentId, params]) => [
      segmentId,
      new Set(params),
    ]),
  );
}

export function buildProjectData(state) {
  const tracks = state.tracks || [];
  return {
    _version: CURRENT_PROJECT_VERSION,
    audioFile: state.audioFile,
    audioDuration: state.audioDuration,
    projectDuration: state.projectDuration,
    frameRate: state.frameRate,
    viewportOrientation: state.viewportOrientation,
    tracks,
    trackIdCounter: state.trackIdCounter,
    sceneSegments: segmentsForType(tracks, 'scene'),
    shaderSegments: segmentsForType(tracks, 'shader'),
    imageSegments: segmentsForType(tracks, 'media'),
    postfxSegments: segmentsForType(tracks, 'postfx'),
    lutSegments: segmentsForType(tracks, 'lut'),
    audioSegments: segmentsForType(tracks, 'audio'),
    audioIdCounter: state.audioIdCounter,
    imageIdCounter: state.imageIdCounter,
    postfxIdCounter: state.postfxIdCounter,
    shaderIdCounter: state.shaderIdCounter,
    sceneIdCounter: state.sceneIdCounter,
    textIdCounter: state.textIdCounter,
    lutIdCounter: state.lutIdCounter,
    keyframeData: state.keyframeData,
    exposedParams: serializeExposedParams(state.exposedParams),
    exposedParamsMeta: state.exposedParamsMeta,
    curveTypes: state.curveTypes,
    lfoData: state.lfoData,
  };
}

export function projectTracksForLoad(project, currentTrackIdCounter = 0) {
  if (project.tracks && project._version >= 7) {
    let tracks = project.tracks.map(track => ({
      ...track,
      segments: (track.segments || []).map(segment => {
        const cleanSegment = { ...segment };
        delete cleanSegment._texturesLoaded;
        return cleanSegment;
      }),
    }));
    let trackIdCounter = project.trackIdCounter ?? currentTrackIdCounter;
    let migrated = false;
    const hasAudioTrack = tracks.some(track => track.type === 'audio');
    if (project.audioFile && !hasAudioTrack) {
      trackIdCounter += 1;
      tracks = tracks.map(track => ({ ...track, order: Number(track.order || 0) + 1 }));
      tracks.unshift({
        id: `track_${trackIdCounter}`,
        type: 'audio',
        name: 'Audio 1',
        order: 0,
        segments: [{
          id: 'audio1',
          name: project.audioFile.split('/').pop().replace(/\.[^.]+$/, ''),
          audioFile: project.audioFile,
          start: 0,
          end: Number(project.audioDuration || 60),
          sourceOffset: 0,
          sourceDuration: Number(project.audioDuration || 60),
          volume: 1,
          muted: false,
        }],
      });
      migrated = true;
    }
    return {
      tracks,
      trackIdCounter,
      migrated,
    };
  }

  let trackIdCounter = 0;
  const tracks = LEGACY_TRACKS.map(([type, name, segmentKey], order) => {
    trackIdCounter += 1;
    return {
      id: `track_${trackIdCounter}`,
      type,
      name,
      order,
      segments: [...(project[segmentKey] || [])],
    };
  });
  if (project.audioFile) {
    trackIdCounter += 1;
    tracks.forEach(track => { track.order += 1; });
    tracks.unshift({
      id: `track_${trackIdCounter}`,
      type: 'audio',
      name: 'Audio 1',
      order: 0,
      segments: [{
        id: 'audio1',
        name: project.audioFile.split('/').pop().replace(/\.[^.]+$/, ''),
        audioFile: project.audioFile,
        start: 0,
        end: Number(project.audioDuration || 60),
        sourceOffset: 0,
        sourceDuration: Number(project.audioDuration || 60),
        volume: 1,
        muted: false,
      }],
    });
  }
  return { tracks, trackIdCounter, migrated: true };
}
