'use strict';

var core_VideoMaker = require('../core/VideoMaker.cjs');
var builder_Track = require('./Track.cjs');
var path = require('path');
var fs = require('fs-extra');

/**
 * 视频构建器 - 多轨道多场景支持（直接使用 Layer，不使用 CompositionElement 嵌套）
 */

/**
 * 视频构建器主类
 */
class VideoBuilder {
  constructor(config = {}) {
    this.config = {
      width: config.width || 1920,
      height: config.height || 1080,
      fps: config.fps || 30,
      // backgroundColor 不再在构造函数中设置，应该通过 Scene 的 addBackground() 添加
      ...config,
    };
    
    this.tracks = [];
    this.currentTime = 0; // 当前时间位置
  }

  /**
   * 创建轨道
   * @param {Object} config - 轨道配置 { zIndex, name }
   * @returns {Track} 轨道实例
   */
  createTrack(config = {}) {
    const track = new builder_Track.Track({
      ...config,
      builder: this,
      zIndex: config.zIndex || this.tracks.length,
    });
    
    this.tracks.push(track);
    return track;
  }

  /**
   * 获取所有轨道
   * @returns {Array<Track>}
   */
  getTracks() {
    return this.tracks;
  }

  /**
   * 计算总时长（所有轨道中最长的）
   * @returns {number} 总时长（秒）
   */
  getTotalDuration() {
    if (this.tracks.length === 0) return 0;
    
    return Math.max(...this.tracks.map(track => track.getTotalDuration()));
  }

  /**
   * 初始化构建器（预加载需要异步加载的元素）
   * @returns {Promise<void>}
   */
  async initialize() {
    // 初始化所有轨道
    for (const track of this.tracks) {
      if (track.initialize) {
        await track.initialize();
      }
    }
  }

  /**
   * 构建最终的 VideoMaker（直接使用 Layer，不使用 CompositionElement 嵌套）
   * @returns {VideoMaker}
   */
  build() {
    const totalDuration = this.getTotalDuration();
    
    // 创建主合成（背景透明，背景应该通过 Scene 的 addBackground() 添加）
    const mainComposition = new core_VideoMaker.VideoMaker({
      width: this.config.width,
      height: this.config.height,
      fps: this.config.fps,
      duration: totalDuration,
      backgroundColor: 'transparent', // 主合成背景透明
    });

    // 移除默认的背景图层（因为背景应该通过 Scene 的 addBackground() 添加）
    if (mainComposition.backgroundLayer) {
      mainComposition.removeLayer(mainComposition.backgroundLayer);
      mainComposition.backgroundLayer = null;
    }

    // 按 zIndex 排序轨道
    const sortedTracks = [...this.tracks].sort((a, b) => a.zIndex - b.zIndex);

    // 收集所有转场信息
    const allTransitions = [];
    for (const track of sortedTracks) {
      // 先收集转场信息并扩展 fromScene 的 duration
      // 这样 track.build() 时会使用扩展后的 duration
      const sortedScenes = [...track.scenes].sort((a, b) => {
        const aStartTime = a.startTime !== undefined ? a.startTime : 0;
        const bStartTime = b.startTime !== undefined ? b.startTime : 0;
        return aStartTime - bStartTime;
      });

      for (let i = 0; i < track.transitions.length; i++) {
        const transition = track.transitions[i];
        const transitionDuration = transition.duration || 0.5;

        // 找到转场对应的from和to场景
        let fromScene = null;
        let toScene = null;
        let transitionStartTime = transition.startTime;

        // 如果transition.startTime未定义，尝试从场景推断
        if (transitionStartTime === undefined) {
          // 遍历场景，找到转场应该插入的位置
          // 假设转场按顺序添加，第 i 个转场应该在第 i 个和第 i+1 个场景之间
          const sceneIndex = i; // 转场索引对应场景索引
          if (sceneIndex < sortedScenes.length - 1) {
            const scene = sortedScenes[sceneIndex];
            const nextScene = sortedScenes[sceneIndex + 1];
            const sceneEndTime = (scene.startTime || 0) + scene.duration;

            // 转场居中在两个场景的交界处
            // 转场开始时间 = sceneEndTime - transitionDuration/2
            // 转场结束时间 = sceneEndTime + transitionDuration/2
            // 这样在 sceneEndTime 时正好是转场的 50% 位置
            fromScene = scene;
            toScene = nextScene;
            transitionStartTime = sceneEndTime - transitionDuration / 2;

            // 计算实际的 transition 时间
            const transitionActualEndTime = transitionStartTime + transitionDuration;

            // 缩短 fromScene 的 duration，让其元素在转场开始时结束显示
            // 转场使用预渲染帧进行混合，不需要依赖主时间轴上的元素
            // 元素 endTime = fromSceneStart + (transitionStartTime - fromSceneStart) = transitionStartTime
            fromScene.duration = transitionStartTime - (fromScene.startTime || 0);

            // 调整 toScene.startTime，让它在 transition 结束后开始
            // 同时调整 duration，保持 scene.endTime 不变
            const originalToSceneEndTime = (toScene.startTime || 0) + toScene.duration;
            toScene.startTime = transitionActualEndTime;
            toScene.duration = originalToSceneEndTime - transitionActualEndTime;
          }
        } else {
          // 转场有指定的startTime，查找对应的场景
          // transition.startTime 是转场开始的时间点
          for (let j = 0; j < sortedScenes.length; j++) {
            const scene = sortedScenes[j];
            const sceneStartTime = scene.startTime !== undefined ? scene.startTime : 0;
            
            // 找到在转场开始时间之后的场景（转场的目标场景）
            if (sceneStartTime >= transitionStartTime) {
              // 找到目标场景，源场景是其前一个场景
              if (j > 0) {
                fromScene = sortedScenes[j - 1];
                toScene = scene;
                break;
              }
            }
          }
        }
        
        if (fromScene && toScene && transitionStartTime !== undefined) {
          // 转场时间计算：
          // transition.startTime 是转场开始的时间点
          // 转场结束时间 = startTime + duration
          const transitionActualStartTime = transitionStartTime;
          const transitionActualEndTime = transitionStartTime + transitionDuration;

          // 确保计算正确
          if (transitionActualStartTime >= transitionActualEndTime) {
            console.warn(`转场 ${transition.name} 时间计算错误: startTime=${transitionActualStartTime}, endTime=${transitionActualEndTime}, transitionStartTime=${transitionStartTime}, duration=${transitionDuration}`);
          }

          const transitionObj = {
            name: transition.name,
            duration: transitionDuration,
            startTime: transitionActualStartTime, // 转场开始时间
            endTime: transitionActualEndTime, // 转场结束时间（目标场景开始时间）
            easing: transition.easing,
            params: transition.params,
            fromScene: fromScene,
            toScene: toScene,
          };

          allTransitions.push(transitionObj);
        } else {
          console.warn(`转场 ${transition.name} 无法找到对应的场景，startTime: ${transitionStartTime}, fromScene: ${fromScene}, toScene: ${toScene}`);
        }
      }

      // Track.build() 现在直接创建 Layer 并添加元素到 VideoMaker
      track.build(mainComposition);
    }

    // 将转场信息保存到composition
    mainComposition.transitions = allTransitions;

    return mainComposition;
  }

  /**
   * 导出视频
   * @param {string} outputPath - 输出路径
   * @param {Object} options - 导出选项
   * @returns {Promise<void>}
   */
  async export(outputPath, options = {}) {
    // 先初始化，预加载所有需要异步加载的元素（如 SVG）
    await this.initialize();
    
    const composition = this.build();
    try {
      await composition.export(outputPath, options);
    } finally {
      composition.destroy();
      // 导出完成后自动销毁 builder
      this.destroy();
    }
  }

  /**
   * 渲染视频（自动 build 和 export）
   * @param {string} outputPath - 输出路径（可选，默认：'output/fkbuilder-video.mp4'）
   * @param {Object} options - 导出选项
   * @returns {Promise<string>} 输出路径
   */
  async render(outputPath, options = {}) {
    // 如果没有提供 outputPath，使用默认路径
    if (!outputPath) {
      const defaultOutputDir = path.join(process.cwd(), 'output');
      await fs.ensureDir(defaultOutputDir);
      outputPath = path.join(defaultOutputDir, 'fkbuilder-video.mp4');
    }

    const composition = this.build();
    try {
      const result = await composition.export(outputPath, options);
      return result || outputPath;
    } finally {
      composition.destroy();
      // 渲染完成后自动销毁 builder
      this.destroy();
    }
  }

  /**
   * 渲染一帧
   * @param {number} time - 时间（秒）
   * @returns {Promise<Canvas>}
   */
  async renderFrame(time) {
    const composition = this.build();
    const canvas = await composition.renderFrame(time);
    composition.destroy();
    return canvas;
  }

  /**
   * 销毁构建器
   */
  destroy() {
    for (const track of this.tracks) {
      track.destroy();
    }
    this.tracks = [];
  }
}

exports.VideoBuilder = VideoBuilder;
//# sourceMappingURL=VideoBuilder.cjs.map
