import { GlRenderer, SoftwareRenderer, IRenderer } from './index';

export type StreamType = 'main' | 'sub' | 'third' | 'fourth';

export interface DisplayConfig {
  /** 视频缩放模式：0=等比缩放(Fit), 1=非等比填满(Fill), 2=等比裁剪(Crop) */
  scalingMode?: number;
  /** JS 渲染层镜像（CSS transform rotateY 180deg），与 C++ SDK 镜像并存 */
  mirrorEnabled?: boolean;
  /** 视频 letterbox 区域背景色，CSS 颜色字符串，默认 'black' */
  backgroundColor?: string;
}

interface RendererEntry {
  renderer: IRenderer;
  config: DisplayConfig;
}

/**
 * RendererManager — 渲染器单例管理器（框架无关）
 *
 * 职责：
 *   - 管理所有视频流的渲染器实例（按 uid + streamType 索引）
 *   - 统一管理 DisplayConfig（scalingMode / mirrorEnabled / backgroundColor）
 *   - 对 React 或其他 UI 框架提供独立的动态更新接口
 *
 * 与 C++ SDK mirror 的关系：
 *   - C++ setLocalVideoMirrorMode / setLocalVideoMirrorModeWithType：影响帧数据 mirror 标志，
 *     决定远端用户所见（编码级别），同时也影响本地显示（通过帧头 mirror 位）
 *   - RendererManager.setMirrorMode：JS 层 CSS transform，纯本地显示覆盖，
 *     不影响编码，不影响远端所见。forceMirror !== undefined 时优先于帧数据 mirror 标志
 */
export class RendererManager {
  private static _instance: RendererManager;
  private entries: Map<string, RendererEntry> = new Map();
  private renderMode: number = 1; // 1=WebGL(GlRenderer), 2=Software(SoftwareRenderer)

  private constructor() {}

  static getInstance(): RendererManager {
    if (!RendererManager._instance) {
      RendererManager._instance = new RendererManager();
    }
    return RendererManager._instance;
  }

  private key(uid: string, streamType: StreamType): string {
    return `${uid}-${streamType}`;
  }

  /** 设置渲染器类型（1=WebGL, 2=Software），在 bind 之前调用 */
  setRenderMode(mode: number): void {
    this.renderMode = mode;
  }

  /**
   * 绑定渲染器到 DOM 元素，并应用初始 DisplayConfig
   * 如果该 (uid, streamType) 已有渲染器，先销毁再重建
   */
  bind(uid: string, streamType: StreamType, element: Element, config?: DisplayConfig): void {
    const k = this.key(uid, streamType);

    // 销毁已有渲染器
    if (this.entries.has(k)) {
      try { this.entries.get(k)!.renderer.unbind(); } catch (e) { /* ignore */ }
      this.entries.delete(k);
    }

    const renderer: IRenderer = this.renderMode === 2
      ? new (SoftwareRenderer as any)()
      : new GlRenderer();

    renderer.bind(element);

    const cfg: DisplayConfig = {
      scalingMode: 0,
      mirrorEnabled: false,
      backgroundColor: 'black',
      ...config,
    };

    renderer.setContentMode(cfg.scalingMode ?? 0);
    renderer.setMirrorMode(cfg.mirrorEnabled ?? false);
    renderer.setBackgroundColor(cfg.backgroundColor ?? 'black');

    this.entries.set(k, { renderer, config: cfg });
  }

  /** 解绑并销毁渲染器 */
  unbind(uid: string, streamType: StreamType): void {
    const k = this.key(uid, streamType);
    if (this.entries.has(k)) {
      try { this.entries.get(k)!.renderer.unbind(); } catch (e) { /* ignore */ }
      this.entries.delete(k);
    }
  }

  /** 推入视频帧数据（由 SDK 帧回调调用） */
  drawFrame(uid: string, streamType: StreamType, imageData: any): void {
    this.entries.get(this.key(uid, streamType))?.renderer.drawFrame(imageData);
  }

  // ── 独立动态更新接口 ──────────────────────────────────────────────────

  /** 动态更新缩放模式（0=Fit, 1=Fill, 2=Crop） */
  setScalingMode(uid: string, streamType: StreamType, mode: number): void {
    const entry = this.entries.get(this.key(uid, streamType));
    if (entry) {
      entry.renderer.setContentMode(mode);
      entry.renderer.refreshCanvas();
      entry.config.scalingMode = mode;
    }
  }

  /**
   * 动态更新 JS 层镜像（CSS transform）
   * 与 C++ SDK 的 setLocalVideoMirrorMode 并存，互不影响
   */
  setMirrorMode(uid: string, streamType: StreamType, enabled: boolean): void {
    const entry = this.entries.get(this.key(uid, streamType));
    if (entry) {
      entry.renderer.setMirrorMode(enabled);
      entry.config.mirrorEnabled = enabled;
    }
  }

  /** 动态更新背景色（letterbox 区域），立即生效 */
  setBackgroundColor(uid: string, streamType: StreamType, color: string): void {
    const entry = this.entries.get(this.key(uid, streamType));
    if (entry) {
      entry.renderer.setBackgroundColor(color);
      entry.config.backgroundColor = color;
    }
  }

  /** 批量更新 DisplayConfig */
  setConfig(uid: string, streamType: StreamType, config: DisplayConfig): void {
    if (config.scalingMode !== undefined) this.setScalingMode(uid, streamType, config.scalingMode);
    if (config.mirrorEnabled !== undefined) this.setMirrorMode(uid, streamType, config.mirrorEnabled);
    if (config.backgroundColor !== undefined) this.setBackgroundColor(uid, streamType, config.backgroundColor);
  }

  /** 读取当前 DisplayConfig（返回副本） */
  getConfig(uid: string, streamType: StreamType): DisplayConfig | null {
    const entry = this.entries.get(this.key(uid, streamType));
    return entry ? { ...entry.config } : null;
  }

  hasRenderer(uid: string, streamType: StreamType): boolean {
    return this.entries.has(this.key(uid, streamType));
  }

  /** 仅供调试：获取渲染器实例 */
  getRenderer(uid: string, streamType: StreamType): IRenderer | null {
    return this.entries.get(this.key(uid, streamType))?.renderer ?? null;
  }
}
