/**
 * @file Canvas 对象池
 * @description 提供 OffscreenCanvas/HTMLCanvasElement 的复用机制，减少内存分配和 GC 压力
 * @module core/utils/canvas-pool
 */

/**
 * Canvas 池条目
 */
export interface PooledCanvas {
  canvas: OffscreenCanvas | HTMLCanvasElement;
  width: number;
  height: number;
  inUse: boolean;
}

interface PoolEntry {
  canvas: OffscreenCanvas | HTMLCanvasElement;
  width: number;
  height: number;
  inUse: boolean;
  lastUsed: number;
}

/**
 * Canvas 对象池
 *
 * 复用 Canvas 元素，避免频繁创建和销毁导致的内存抖动
 *
 * @example
 * ```typescript
 * const pool = new CanvasPool();
 * const acquired = pool.acquire(640, 480);
 * // 使用 canvas 进行绘制...
 * pool.release(acquired);
 * ```
 */
export class CanvasPool {
  private _pool: PoolEntry[] = [];
  private _maxSize: number = 4;
  private _useOffscreen: boolean;

  /**
   * 创建 Canvas 池
   * @param maxSize 最大池大小
   * @param useOffscreen 是否使用 OffscreenCanvas
   */
  constructor(maxSize: number = 4, useOffscreen: boolean = true) {
    this._maxSize = maxSize;
    this._useOffscreen = useOffscreen && typeof OffscreenCanvas !== 'undefined';
  }

  /**
   * 从池中获取 Canvas
   *
   * 1. 查找尺寸匹配的可用 canvas（允许 10% 误差）
   * 2. 无匹配则创建新的
   * 3. 超出 _maxSize 则回收最旧的 inUse=false 的
   * 4. 返回 PooledCanvas，标记 inUse=true
   *
   * @param width  宽度
   * @param height 高度
   */
  acquire(width: number, height: number): PooledCanvas {
    // 1. 查找尺寸匹配的可用 canvas（允许 10% 误差）
    const matched = this._pool.find(p =>
      !p.inUse &&
      Math.abs(p.width - width) / width <= 0.1 &&
      Math.abs(p.height - height) / height <= 0.1
    );

    if (matched) {
      matched.inUse = true;
      matched.lastUsed = Date.now();
      return {
        canvas: matched.canvas,
        width: matched.width,
        height: matched.height,
        inUse: true,
      };
    }

    // 2. 无匹配则创建新的
    let canvas: OffscreenCanvas | HTMLCanvasElement;
    if (this._useOffscreen) {
      canvas = new OffscreenCanvas(width, height);
    } else {
      // 在非 OffscreenCanvas 环境（如 Node.js 测试）回退到 HTMLCanvasElement
      if (typeof document !== 'undefined') {
        canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
      } else {
        // 无法创建 canvas
        throw new Error('CanvasPool: 无法创建 canvas (OffscreenCanvas 不可用，且 document 不存在)');
      }
    }

    const entry: PoolEntry = {
      canvas,
      width,
      height,
      inUse: true,
      lastUsed: Date.now(),
    };

    // 3. 超出 _maxSize 则回收最旧的 inUse=false 的
    if (this._pool.length >= this._maxSize) {
      const oldestIdx = this._findOldestAvailableIndex();
      if (oldestIdx !== -1) {
        this._pool.splice(oldestIdx, 1);
      }
    }

    this._pool.push(entry);
    return {
      canvas: entry.canvas,
      width: entry.width,
      height: entry.height,
      inUse: true,
    };
  }

  /**
   * 归还 Canvas 到池中
   * @param pooled 要归还的 PooledCanvas
   */
  release(pooled: PooledCanvas): void {
    const entry = this._pool.find(p => p.canvas === pooled.canvas);
    if (entry) {
      entry.inUse = false;
      entry.lastUsed = Date.now();
    }
  }

  /**
   * 清空池
   */
  clear(): void {
    this._pool = [];
  }

  /**
   * 获取池统计信息
   */
  getStats(): { total: number; inUse: number; available: number } {
    return {
      total: this._pool.length,
      inUse: this._pool.filter(p => p.inUse).length,
      available: this._pool.filter(p => !p.inUse).length,
    };
  }

  /**
   * 查找最旧的可用条目索引
   */
  private _findOldestAvailableIndex(): number {
    let oldestIdx = -1;
    let oldestTime = Infinity;
    for (let i = 0; i < this._pool.length; i++) {
      if (!this._pool[i].inUse && this._pool[i].lastUsed < oldestTime) {
        oldestTime = this._pool[i].lastUsed;
        oldestIdx = i;
      }
    }
    return oldestIdx;
  }
}

/** 全局共享的 Canvas 池实例 */
export const globalCanvasPool = new CanvasPool();