'use strict';

var elements_TextElement = require('../elements/TextElement.cjs');
var elements_ImageElement = require('../elements/ImageElement.cjs');
var elements_VideoElement = require('../elements/VideoElement.cjs');
var elements_RectElement = require('../elements/RectElement.cjs');
var elements_CircleElement = require('../elements/CircleElement.cjs');
var elements_PathElement = require('../elements/PathElement.cjs');
var elements_SVGElement = require('../elements/SVGElement.cjs');
var elements_JSONElement = require('../elements/JSONElement.cjs');
var elements_AudioElement = require('../elements/AudioElement.cjs');
var elements_SubtitleElement = require('../elements/SubtitleElement.cjs');
var elements_OscilloscopeElement = require('../elements/OscilloscopeElement.cjs');
var elements_CodeElement = require('../elements/CodeElement.cjs');
var elements_EChartsElement = require('../elements/EChartsElement.cjs');
var elements_SpriteElement = require('../elements/SpriteElement.cjs');
var utils_lrcSubtitleBuilder = require('../utils/lrcSubtitleBuilder.cjs');
var builder_Component = require('./Component.cjs');

/**
 * 场景类 - 直接使用 Layer 方式构建
 */

/**
 * 场景类 - 直接返回元素实例数组，不使用 CompositionElement
 */
class Scene {
  constructor(config = {}) {
    this.track = config.track;
    this.startTime = config.startTime; // 可选，如果不指定则自动计算
    this.duration = config.duration || 5;
    this.name = config.name || `Scene-${this.track?.scenes?.length || 0}`;
    this.width = config.width || config.track?.width || config.track?.builder?.config?.width || 1920;
    this.height = config.height || config.track?.height || config.track?.builder?.config?.height || 1080;
    this.fps = config.fps || config.track?.fps || config.track?.builder?.config?.fps || 30;
    
    this.elements = [];
    this.backgroundLayer = null;
    this.components = []; // 组件列表
    this.subtitleCursor = 0; // 字幕自动播放游标，未指定 startTime 时按累加顺序播放
  }

  /**
   * 添加背景
   * @param {Object} config - 背景配置 { color, image, ... }
   * @returns {Scene} 返回自身以支持链式调用
   */
  addBackground(config = {}) {
    // 预设颜色列表（参考 FKVideo）
    const presetColors = [
      "#4ecdc4", // 青色
      "#45b7d1", // 蓝色
      "#f39c12", // 橙色
      "#e74c3c", // 深红色
      "#9b59b6", // 紫色
      "#1abc9c", // 青绿色
      "#2ecc71", // 绿色
      "#f1c40f", // 黄色
      "#34495e", // 深灰色
      "#16a085", // 深青绿色
      "#27ae60", // 深绿色
      "#2980b9", // 深蓝色
      "#8e44ad", // 深紫色
      "#c0392b", // 深红色
      "#d35400", // 深橙色
      "#e67e22", // 橙色
      "#3498db", // 天蓝色
      "#95a5a6", // 浅灰色
    ];
    
    // 如果没有指定颜色，随机选择一个预设颜色
    // 处理 config 是字符串的情况（即直接传入颜色值）
    let backgroundColor = typeof config === 'string' ? config : (config.color || config.backgroundColor);
    if (!backgroundColor) {
      const randomIndex = Math.floor(Math.random() * presetColors.length);
      backgroundColor = presetColors[randomIndex];
    }
    
    // 如果已经有背景图层，更新它
    if (!this.backgroundLayer) {
      this.backgroundLayer = {
        type: 'background',
        config: {
          backgroundColor: backgroundColor,
          ...(typeof config === 'object' && config ? config : {}),
        },
      };
    } else {
      this.backgroundLayer.config = {
        ...this.backgroundLayer.config,
        backgroundColor: backgroundColor,
        ...(typeof config === 'object' && config ? config : {}),
      };
    }
    
    return this;
  }

  /**
   * 添加文本元素
   * @param {Object} config - 文本配置
   * @returns {Scene} 返回自身以支持链式调用
   */
  addText(config = {}) {
    this.elements.push({
      type: 'text',
      element: new elements_TextElement.TextElement(config),
    });
    return this;
  }

  /**
   * 添加图片元素
   * @param {Object} config - 图片配置
   * @returns {Scene} 返回自身以支持链式调用
   */
  addImage(config = {}) {
    // 跳过没有 src 的图片元素
    if (!config.src || !config.src.trim()) {
      //console.warn(`[Scene] addImage: 跳过空的图片元素 ${config.id || 'unknown'}`);
      return this;
    }
    const imageElement = new elements_ImageElement.ImageElement(config);
    // 如果提供了src，异步加载图片
    this.elements.push({
      type: 'image',
      element: imageElement,
    });
    return this;
  }

  addSprite(config = {}) {
    const spriteElement = new elements_SpriteElement.SpriteElement(config);
    this.elements.push({
      type: 'sprite',
      element: spriteElement,
    });
    return this;
  }

  /**
   * 添加视频元素
   * @param {Object} config - 视频配置
   * @returns {Scene} 返回自身以支持链式调用
   */
  addVideo(config = {}) {
    // 跳过没有 src 的视频元素
    if (!config.src || !config.src.trim()) {
      //console.warn(`[Scene] addVideo: 跳过空的视频元素 ${config.id || 'unknown'}`);
      return this;
    }
    const videoElement = new elements_VideoElement.VideoElement(config);
    // 如果提供了src，异步初始化视频
    this.elements.push({
      type: 'video',
      element: videoElement,
    });
    return this;
  }

  /**
   * 添加矩形元素
   * @param {Object} config - 矩形配置
   * @returns {Scene} 返回自身以支持链式调用
   */
  addRect(config = {}) {
    this.elements.push({
      type: 'rect',
      element: new elements_RectElement.RectElement(config),
    });
    return this;
  }

  /**
   * 添加圆形元素
   * @param {Object} config - 圆形配置
   * @returns {Scene} 返回自身以支持链式调用
   */
  addCircle(config = {}) {
    this.elements.push({
      type: 'circle',
      element: new elements_CircleElement.CircleElement(config),
    });
    return this;
  }

  /**
   * 添加路径元素
   * @param {Object} config - 路径配置
   * @returns {Scene} 返回自身以支持链式调用
   */
  addPath(config = {}) {
    this.elements.push({
      type: 'path',
      element: new elements_PathElement.PathElement(config),
    });
    return this;
  }

  /**
   * 添加 SVG 元素
   * @param {Object} config - SVG 配置 { 
   *   src, svgString, width, height, fit, ...,
   *   onLoaded: (svgElement, time) => void,  // SVG 加载完成后的回调
   *   onRender: (svgElement, time) => void,  // 每次渲染时的回调
   *   onFrame: (svgElement, event, paperItem) => void  // Paper.js onFrame 回调
   * }
   * @returns {Scene} 返回自身以支持链式调用
   */
  addSVG(config = {}) {
    const svgElement = new elements_SVGElement.SVGElement(config);
    // SVG 会在 build 时或渲染时自动加载，不需要在这里立即加载
    // 这样可以支持链式调用
    this.elements.push({
      type: 'svg',
      element: svgElement,
    });
    return this; // 返回 this 以支持链式调用
  }

  /**
   * 添加 JSON 元素（支持 Paper.js JSON 格式）
   * @param {Object} config - JSON 配置 { src, jsonString, jsonData, width, height, fit, ... }
   * @returns {Scene} 返回自身以支持链式调用
   */
  addJSON(config = {}) {
    const jsonElement = new elements_JSONElement.JSONElement(config);
    // 如果提供了 src，异步加载 JSON
    this.elements.push({
      type: 'json',
      element: jsonElement,
    });
    return this;
  }

  addSprite(config = {}) {
    const spriteElement = new elements_SpriteElement.SpriteElement(config);
    this.elements.push({
      type: 'sprite',
      element: spriteElement,
    });
    return this;
  }

  /**
   * 添加字幕元素
   * 同一场景内多次调用 addSubtitle 且未指定 startTime 时，会按调用顺序自动顺序播放；
   * 场景的 duration 也会自动延长到能容纳所有字幕。
   * @param {Object} config - 字幕配置
   * @returns {Scene} 返回自身以支持链式调用
   */
  addSubtitle(config = {}) {
    const hasExplicitStartTime = config.startTime !== undefined && config.startTime !== null;
    const resolvedStartTime = hasExplicitStartTime ? config.startTime : this.subtitleCursor;
    const resolvedDuration = config.duration || 0;

    this.elements.push({
      type: 'subtitle',
      element: new elements_SubtitleElement.SubtitleElement({
        ...config,
        startTime: resolvedStartTime,
      }),
    });

    // 推进游标：取 (当前游标) 与 (本次字幕结束时间) 的较大值
    this.subtitleCursor = Math.max(this.subtitleCursor, resolvedStartTime + resolvedDuration);

    // 自动延长场景时长以容纳所有字幕
    if (this.subtitleCursor > this.duration) {
      this.duration = this.subtitleCursor;
    }

    return this;
  }

  /**
   * 从 LRC 文件添加歌词字幕（同步方式）
   * @param {string} lrcPath - LRC 文件路径
   * @param {Object} options - 字幕样式选项
   * @returns {Scene} 返回自身以支持链式调用
   */
  addLRC(lrcPath, options = {}) {
    utils_lrcSubtitleBuilder.LRCSubtitleBuilder.addSubtitlesFromLRC(this, lrcPath, options);
    return this;
  }

  /**
   * 添加音频元素
   * @param {Object} config - 音频配置 { src, startTime, duration, volume, fadeIn, fadeOut, loop }
   * @returns {Scene} 返回自身以支持链式调用
   */
  addAudio(config = {}) {
    const audioElement = new elements_AudioElement.AudioElement(config);
    // 异步加载音频信息
    this.elements.push({
      type: 'audio',
      element: audioElement,
    });
    return this;
  }

  /**
   * 添加示波器元素
   * @param {Object} config - 示波器配置 { audioPath, waveColor, style, width, height, ... }
   * @returns {Scene} 返回自身以支持链式调用
   */
  addOscilloscope(config = {}) {
    const oscilloscopeElement = new elements_OscilloscopeElement.OscilloscopeElement(config);
    // 初始化会在渲染时自动调用，不需要在这里手动加载
    // 这样可以支持链式调用，同时确保在渲染前数据已准备好
    this.elements.push({
      type: 'oscilloscope',
      element: oscilloscopeElement,
    });
    return this;
  }

  /**
   * 添加自定义元素
   * @param {BaseElement} element - 元素实例
   * @returns {Scene} 返回自身以支持链式调用
   */
  addElement(element) {
    this.elements.push({
      type: 'custom',
      element: element,
    });
    return this;
  }

  /**
   * 添加代码元素（便利方法）
   * @param {Object} config - code element 配置
   */
  addCode(config = {}) {
    const codeEl = new elements_CodeElement.CodeElement(config);
    this.elements.push({ type: 'code', element: codeEl });
    return this;
  }

  addECharts(config = {}) {
    const el = new elements_EChartsElement.EChartsElement(config);
    this.elements.push({ type: 'echarts', element: el });
    return this;
  }

  /**
   * 添加 Sprite 精灵图元素
   * @param {Object} config - Sprite 配置
   * @returns {Scene} 返回自身以支持链式调用
   */
  addSprite(config = {}) {
    const el = new elements_SpriteElement.SpriteElement(config);
    this.elements.push({ type: 'sprite', element: el });
    return this;
  }

  /**
   * 添加组件
   * @param {Component|Object} component - 组件实例或组件配置
   * @returns {Scene} 返回自身以支持链式调用
   */
  addComponent(component) {
    // 如果传入的是配置对象，创建组件实例
    if (!(component instanceof builder_Component.Component)) {
      component = new builder_Component.Component(component);
    }
    
    // 设置父容器引用
    component.parent = this;
    component.parentType = 'scene';
    
    this.components.push(component);
    return this;
  }

  /**
   * 获取所有元素
   * @returns {Array}
   */
  getElements() {
    // 过滤掉没有 src 的图片和没有 videoPath/src 的视频元素
    return this.elements
      .filter(e => {
        if (e.type === 'image' && !e.element.src) {
          //console.warn(`[Scene] getElements 跳过无效元素: ${e.type} 缺少 src`);
          return false;
        }
        if (e.type === 'video' && !e.element.videoPath) {
          //console.warn(`[Scene] getElements 跳过无效元素: ${e.type} 缺少 videoPath`);
          return false;
        }
        return true;
      })
      .map(e => e.element);
  }

  /**
   * 初始化场景（预加载需要异步加载的元素）
   * @returns {Promise<void>}
   */
  async initialize() {
    // 预加载所有需要异步加载的元素，使用统一的 initialize 方法
    for (const { element } of this.elements) {
      if (element && typeof element.initialize === 'function') {
        try {
          const initResult = element.initialize();
          // 如果返回 Promise，等待完成
          if (initResult && typeof initResult.then === 'function') {
            await initResult;
          }
        } catch (err) {
          console.warn(`[Scene] 元素 ${element.type} 初始化失败:`, err);
        }
      }
    }
    
    // 初始化所有组件
    for (const component of this.components) {
      if (component && typeof component.initialize === 'function') {
        try {
          await component.initialize();
        } catch (err) {
          console.warn(`[Scene] 组件 ${component.name} 初始化失败:`, err);
        }
      }
    }
  }

  /**
   * 构建场景（返回元素实例数组，不使用 CompositionElement）
   * @param {number} sceneStartTime - 场景在轨道中的开始时间（绝对时间）
   * @returns {Array<BaseElement>} 元素实例数组
   */
  build(sceneStartTime = 0) {
    const elementInstances = [];
    
    // 添加背景（作为矩形元素）
    // 注意：Paper.js 的原点在画布左上角 (0, 0)，所以背景矩形应该从 (0, 0) 开始
    if (this.backgroundLayer) {
      const backgroundElement = new elements_RectElement.RectElement({
        x: this.width / 2, // 画布中心 X（因为 anchor 是 [0.5, 0.5]，所以需要设置为中心）
        y: this.height / 2, // 画布中心 Y
        width: this.width,
        height: this.height,
        anchor: [0.5, 0.5], // 以中心为锚点，这样矩形会从 (0, 0) 到 (width, height)
        bgcolor: this.backgroundLayer.config.backgroundColor,
        startTime: 0, // 相对于场景的开始时间
        duration: this.duration,
        zIndex: -9999,
      });
      elementInstances.push(backgroundElement);
    }

    // 添加所有元素实例
    for (const { element, type } of this.elements) {
      // 元素的时间是相对于场景的，需要确保正确设置
      if (element) {
        // 过滤没有 src 的图片和没有 videoPath 的视频元素
        if (type === 'image' && !element.src) {
          //console.warn(`[Scene] 跳过无效元素: ${type} 缺少 src`);
          continue;
        }
        if (element.type === 'video' && !element.videoPath) {
          //console.warn(`[Scene] 跳过无效元素: ${type} 缺少 videoPath`);
          continue;
        }
        // 如果元素没有设置 startTime，默认为 0（相对于场景开始）
        if (element.startTime === undefined) {
          element.startTime = 0;
        }
        // 确保元素的 endTime 正确
        if (element.duration !== undefined && element.endTime === Infinity) {
          element.endTime = element.startTime + element.duration;
        }
        elementInstances.push(element);
      }
    }

    // 添加所有组件的元素（组件会将其内部元素转换为绝对坐标）
    // 注意：组件 build 返回的元素时间已经是绝对时间（相对于视频开始），不需要再次转换
    for (const component of this.components) {
      if (component && component.visible) {
        const componentElements = component.build(sceneStartTime, this.width, this.height);
        // 标记这些元素来自组件，时间已经是绝对时间
        for (const element of componentElements) {
          element._fromComponent = true;
        }
        elementInstances.push(...componentElements);
      }
    }

    return elementInstances;
  }

  /**
   * 将元素实例转换为配置对象
   * @param {BaseElement} element - 元素实例
   * @returns {Object} 元素配置对象
   */
  elementToConfig(element) {
    if (!element) return null;
    
    // 元素的属性可能存储在 element.config 中，也可能直接作为 element 的属性
    // 优先从 element.config 读取，如果没有则从 element 本身读取
    const elementConfig = element.config || {};
    
    // 获取元素的所有属性
    const config = {
      type: element.type,
      x: element.x !== undefined ? element.x : elementConfig.x,
      y: element.y !== undefined ? element.y : elementConfig.y,
      width: element.width !== undefined ? element.width : elementConfig.width,
      height: element.height !== undefined ? element.height : elementConfig.height,
      startTime: element.startTime,
      duration: element.duration,
      zIndex: element.zIndex !== undefined ? element.zIndex : elementConfig.zIndex,
      opacity: element.opacity !== undefined ? element.opacity : elementConfig.opacity,
      anchor: element.anchor || elementConfig.anchor,
      animations: element.animations || elementConfig.animations,
    };

    // 根据元素类型添加特定属性
    if (element.type === 'text') {
      config.text = element.text !== undefined ? element.text : elementConfig.text;
      config.fontSize = element.fontSize !== undefined ? element.fontSize : elementConfig.fontSize;
      config.color = element.color !== undefined ? element.color : elementConfig.color;
      config.fontFamily = element.fontFamily !== undefined ? element.fontFamily : elementConfig.fontFamily;
      config.textAlign = element.textAlign !== undefined ? element.textAlign : elementConfig.textAlign;
      config.stroke = element.stroke !== undefined ? element.stroke : elementConfig.stroke;
      config.strokeColor = element.strokeColor !== undefined ? element.strokeColor : elementConfig.strokeColor;
      config.strokeWidth = element.strokeWidth !== undefined ? element.strokeWidth : elementConfig.strokeWidth;
      config.split = element.split !== undefined ? element.split : elementConfig.split;
      config.splitDelay = element.splitDelay !== undefined ? element.splitDelay : elementConfig.splitDelay;
      config.splitDuration = element.splitDuration !== undefined ? element.splitDuration : elementConfig.splitDuration;
    } else if (element.type === 'subtitle') {
      config.text = element.text !== undefined ? element.text : elementConfig.text;
      config.fontSize = element.fontSize !== undefined ? element.fontSize : elementConfig.fontSize;
      config.color = element.color !== undefined ? element.color : (element.textColor !== undefined ? element.textColor : elementConfig.color);
      config.textColor = element.textColor !== undefined ? element.textColor : elementConfig.textColor;
      config.fontFamily = element.fontFamily !== undefined ? element.fontFamily : elementConfig.fontFamily;
      config.textAlign = element.textAlign !== undefined ? element.textAlign : elementConfig.textAlign;
      config.split = element.split !== undefined ? element.split : elementConfig.split;
      config.splitDelay = element.splitDelay !== undefined ? element.splitDelay : elementConfig.splitDelay;
      config.splitDuration = element.splitDuration !== undefined ? element.splitDuration : elementConfig.splitDuration;
      config.animations = element.animations !== undefined ? element.animations : elementConfig.animations;
    } else if (element.type === 'image') {
      config.src = element.src !== undefined ? element.src : elementConfig.src;
      config.fit = element.fit !== undefined ? element.fit : elementConfig.fit;
    } else if (element.type === 'rect') {
      config.fillColor = element.fillColor || element.bgcolor || elementConfig.fillColor || elementConfig.bgcolor;
      config.strokeColor = element.strokeColor || element.borderColor || elementConfig.strokeColor || elementConfig.borderColor;
      config.strokeWidth = element.strokeWidth || element.borderWidth || elementConfig.strokeWidth || elementConfig.borderWidth;
    } else if (element.type === 'circle') {
      config.radius = element.radius !== undefined ? element.radius : elementConfig.radius;
      config.fillColor = element.fillColor !== undefined ? element.fillColor : elementConfig.fillColor;
      config.strokeColor = element.strokeColor !== undefined ? element.strokeColor : elementConfig.strokeColor;
      config.strokeWidth = element.strokeWidth !== undefined ? element.strokeWidth : elementConfig.strokeWidth;
    } else if (element.type === 'audio') {
      config.src = element.src !== undefined ? element.src : elementConfig.src;
      config.audioPath = element.audioPath !== undefined ? element.audioPath : elementConfig.audioPath;
      // 支持 cutFrom 和 cutTo（新方式）以及 audioStartTime 和 audioEndTime（旧方式）
      config.cutFrom = element.cutFrom !== undefined ? element.cutFrom : (element.audioStartTime !== undefined ? element.audioStartTime : elementConfig.cutFrom);
      config.cutTo = element.cutTo !== undefined ? element.cutTo : (element.audioEndTime !== undefined ? element.audioEndTime : elementConfig.cutTo);
      config.volume = element.volume !== undefined ? element.volume : elementConfig.volume;
      config.fadeIn = element.fadeIn !== undefined ? element.fadeIn : elementConfig.fadeIn;
      config.fadeOut = element.fadeOut !== undefined ? element.fadeOut : elementConfig.fadeOut;
      config.loop = element.loop !== undefined ? element.loop : elementConfig.loop;
    } else if (element.type === 'sprite') {
      config.spriteType = element.spriteType !== undefined ? element.spriteType : elementConfig.spriteType;
      config.spriteConfig = element.spriteConfig !== undefined ? element.spriteConfig : elementConfig.spriteConfig;
      config.frames = element.frames !== undefined ? element.frames : elementConfig.frames;
      config.frameRate = element.frameRate !== undefined ? element.frameRate : elementConfig.frameRate;
      config.loop = element.loop !== undefined ? element.loop : elementConfig.loop;
      config.autoplay = element.autoplay !== undefined ? element.autoplay : elementConfig.autoplay;
      config.playMode = element.playMode !== undefined ? element.playMode : elementConfig.playMode;
      config.fit = element.fit !== undefined ? element.fit : elementConfig.fit;
      config.preserveAspectRatio = element.preserveAspectRatio !== undefined ? element.preserveAspectRatio : elementConfig.preserveAspectRatio;
      config.src = element.src !== undefined ? element.src : elementConfig.src;
      config.columns = element.columns !== undefined ? element.columns : elementConfig.columns;
      config.rows = element.rows !== undefined ? element.rows : elementConfig.rows;
      config.frameWidth = element.frameWidth !== undefined ? element.frameWidth : elementConfig.frameWidth;
      config.frameHeight = element.frameHeight !== undefined ? element.frameHeight : elementConfig.frameHeight;
      config.frameCount = element.frameCount !== undefined ? element.frameCount : elementConfig.frameCount;
      config.margin = element.margin !== undefined ? element.margin : elementConfig.margin;
      config.spacing = element.spacing !== undefined ? element.spacing : elementConfig.spacing;
      config.startIndex = element.startIndex !== undefined ? element.startIndex : elementConfig.startIndex;
      config.orientation = element.orientation !== undefined ? element.orientation : elementConfig.orientation;
    }

    return config;
  }

  /**
   * 销毁场景
   */
  destroy() {
    for (const { element } of this.elements) {
      if (element.destroy) {
        element.destroy();
      }
    }
    this.elements = [];
    this.backgroundLayer = null;
    
    // 销毁所有组件
    for (const component of this.components) {
      if (component.destroy) {
        component.destroy();
      }
    }
    this.components = [];
  }
}

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