/**
 * 液化对象引用管理器
 * 专门处理液化操作中的对象引用管理，避免引用丢失问题
 */
export class LiquifyReferenceManager {
  constructor() {
    // 对象引用池
    this.objectRefs = new Map();
    // 状态快照池
    this.stateSnapshots = new Map();
    // ImageData缓存池
    this.imageDataCache = new Map();
    // 事件监听器备份
    this.eventListeners = new Map();
  }

  /**
   * 注册对象到引用管理器
   * @param {Object} fabricObject Fabric对象
   * @param {String} objectId 对象唯一ID
   * @returns {String} 引用ID
   */
  registerObject(fabricObject, objectId) {
    const refId = objectId || this._generateRefId();

    // 保存对象引用
    this.objectRefs.set(refId, fabricObject);

    // 备份事件监听器
    this._backupEventListeners(refId, fabricObject);

    // 创建初始状态快照
    this._createStateSnapshot(refId, fabricObject);

    console.log(`📝 对象已注册到引用管理器: ${refId}`);
    return refId;
  }

  /**
   * 获取对象引用
   * @param {String} refId 引用ID
   * @returns {Object|null} Fabric对象
   */
  getObjectRef(refId) {
    return this.objectRefs.get(refId) || null;
  }

  /**
   * 更新对象的图像数据，保持引用不变
   * @param {String} refId 引用ID
   * @param {ImageData} newImageData 新的图像数据
   * @returns {Promise<Boolean>} 更新结果
   */
  async updateObjectImageData(refId, newImageData) {
    const fabricObject = this.objectRefs.get(refId);
    if (!fabricObject || !newImageData) {
      throw new Error(`无法更新对象图像数据: 对象不存在或数据无效 (${refId})`);
    }

    return new Promise((resolve, reject) => {
      try {
        // 创建临时canvas
        const tempCanvas = document.createElement("canvas");
        tempCanvas.width = newImageData.width;
        tempCanvas.height = newImageData.height;
        const tempCtx = tempCanvas.getContext("2d");
        tempCtx.putImageData(newImageData, 0, 0);

        // 创建新的图像元素
        const img = new Image();
        img.onload = () => {
          try {
            // 保存当前状态
            const currentState = this._captureObjectState(fabricObject);

            // 更新图像源
            if (fabricObject.setElement) {
              fabricObject.setElement(img);
            } else if (fabricObject._element) {
              fabricObject._element = img;
              fabricObject._originalElement = img;
            }

            // 恢复非图像属性
            this._restoreObjectState(fabricObject, currentState);

            // 标记需要重新渲染
            fabricObject.dirty = true;
            fabricObject.setCoords();

            // 更新缓存
            this._updateImageDataCache(refId, newImageData);

            console.log(`✅ 对象图像数据更新成功: ${refId}`);
            resolve(true);
          } catch (error) {
            console.error("更新对象状态失败:", error);
            reject(error);
          }
        };

        img.onerror = () => {
          reject(new Error("加载图像数据失败"));
        };

        img.src = tempCanvas.toDataURL();
      } catch (error) {
        console.error("创建临时canvas失败:", error);
        reject(error);
      }
    });
  }

  /**
   * 创建对象状态快照
   * @param {String} refId 引用ID
   * @param {String} snapshotId 快照ID
   * @returns {String} 快照ID
   */
  createSnapshot(refId, snapshotId = null) {
    const fabricObject = this.objectRefs.get(refId);
    if (!fabricObject) {
      throw new Error(`无法创建快照: 对象不存在 (${refId})`);
    }

    const snapId = snapshotId || `${refId}_${Date.now()}`;
    const snapshot = this._createStateSnapshot(snapId, fabricObject);

    console.log(`📸 已创建对象快照: ${snapId}`);
    return snapId;
  }

  /**
   * 恢复对象到指定快照状态
   * @param {String} refId 引用ID
   * @param {String} snapshotId 快照ID
   * @returns {Promise<Boolean>} 恢复结果
   */
  async restoreFromSnapshot(refId, snapshotId) {
    const fabricObject = this.objectRefs.get(refId);
    const snapshot = this.stateSnapshots.get(snapshotId);

    if (!fabricObject || !snapshot) {
      throw new Error(`无法恢复快照: 对象或快照不存在 (${refId}, ${snapshotId})`);
    }

    // 恢复图像数据
    if (snapshot.imageData) {
      await this.updateObjectImageData(refId, snapshot.imageData);
    }

    // 恢复对象属性
    if (snapshot.properties) {
      this._restoreObjectState(fabricObject, snapshot.properties);
    }

    // 恢复事件监听器
    if (snapshot.eventListeners) {
      this._restoreEventListeners(refId, fabricObject, snapshot.eventListeners);
    }

    console.log(`🔄 对象快照恢复成功: ${refId} -> ${snapshotId}`);
    return true;
  }

  /**
   * 批量更新多个对象
   * @param {Array} updates 更新列表 [{refId, imageData}, ...]
   * @returns {Promise<Array>} 更新结果
   */
  async batchUpdate(updates) {
    const results = [];

    for (const update of updates) {
      try {
        const result = await this.updateObjectImageData(update.refId, update.imageData);
        results.push({ refId: update.refId, success: true, result });
      } catch (error) {
        console.error(`批量更新失败 ${update.refId}:`, error);
        results.push({
          refId: update.refId,
          success: false,
          error: error.message,
        });
      }
    }

    return results;
  }

  /**
   * 清理不再使用的引用
   * @param {String} refId 引用ID
   */
  cleanup(refId) {
    this.objectRefs.delete(refId);
    this.stateSnapshots.delete(refId);
    this.imageDataCache.delete(refId);
    this.eventListeners.delete(refId);

    console.log(`🗑️ 已清理对象引用: ${refId}`);
  }

  /**
   * 清理所有引用
   */
  cleanupAll() {
    this.objectRefs.clear();
    this.stateSnapshots.clear();
    this.imageDataCache.clear();
    this.eventListeners.clear();

    console.log("🗑️ 已清理所有对象引用");
  }

  /**
   * 获取内存使用统计
   * @returns {Object} 统计信息
   */
  getMemoryStats() {
    return {
      objectRefs: this.objectRefs.size,
      stateSnapshots: this.stateSnapshots.size,
      imageDataCache: this.imageDataCache.size,
      eventListeners: this.eventListeners.size,
      totalMemoryUsage: this._calculateMemoryUsage(),
    };
  }

  // 私有方法

  /**
   * 生成引用ID
   * @returns {String} 引用ID
   * @private
   */
  _generateRefId() {
    return `ref_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  /**
   * 备份事件监听器
   * @param {String} refId 引用ID
   * @param {Object} fabricObject Fabric对象
   * @private
   */
  _backupEventListeners(refId, fabricObject) {
    const listeners = {};

    // 备份常见的事件监听器
    const eventTypes = ["mousedown", "mouseup", "mousemove", "mouseout", "mouseover"];

    eventTypes.forEach((eventType) => {
      if (fabricObject.__eventListeners && fabricObject.__eventListeners[eventType]) {
        listeners[eventType] = [...fabricObject.__eventListeners[eventType]];
      }
    });

    this.eventListeners.set(refId, listeners);
  }

  /**
   * 恢复事件监听器
   * @param {String} refId 引用ID
   * @param {Object} fabricObject Fabric对象
   * @param {Object} listeners 监听器备份
   * @private
   */
  _restoreEventListeners(refId, fabricObject, listeners) {
    Object.keys(listeners).forEach((eventType) => {
      if (listeners[eventType] && listeners[eventType].length > 0) {
        listeners[eventType].forEach((listener) => {
          fabricObject.on(eventType, listener);
        });
      }
    });
  }

  /**
   * 创建状态快照
   * @param {String} snapId 快照ID
   * @param {Object} fabricObject Fabric对象
   * @returns {Object} 快照数据
   * @private
   */
  _createStateSnapshot(snapId, fabricObject) {
    const snapshot = {
      timestamp: Date.now(),
      properties: this._captureObjectState(fabricObject),
      imageData: this._captureImageData(fabricObject),
      eventListeners: this.eventListeners.get(snapId.split("_")[0]) || {},
    };

    this.stateSnapshots.set(snapId, snapshot);
    return snapshot;
  }

  /**
   * 捕获对象状态
   * @param {Object} fabricObject Fabric对象
   * @returns {Object} 对象状态
   * @private
   */
  _captureObjectState(fabricObject) {
    return {
      left: fabricObject.left,
      top: fabricObject.top,
      scaleX: fabricObject.scaleX,
      scaleY: fabricObject.scaleY,
      angle: fabricObject.angle,
      flipX: fabricObject.flipX,
      flipY: fabricObject.flipY,
      opacity: fabricObject.opacity,
      visible: fabricObject.visible,
      selectable: fabricObject.selectable,
      evented: fabricObject.evented,
      id: fabricObject.id,
      layerId: fabricObject.layerId,
      customData: fabricObject.customData ? { ...fabricObject.customData } : {},
      filters: fabricObject.filters ? [...fabricObject.filters] : [],
    };
  }

  /**
   * 恢复对象状态
   * @param {Object} fabricObject Fabric对象
   * @param {Object} state 状态数据
   * @private
   */
  _restoreObjectState(fabricObject, state) {
    if (!state) return;

    fabricObject.set({
      left: state.left,
      top: state.top,
      scaleX: state.scaleX,
      scaleY: state.scaleY,
      angle: state.angle,
      flipX: state.flipX,
      flipY: state.flipY,
      opacity: state.opacity,
      visible: state.visible,
      selectable: state.selectable,
      evented: state.evented,
    });

    // 恢复自定义属性
    if (state.customData) {
      fabricObject.customData = { ...state.customData };
    }

    // 恢复滤镜
    if (state.filters && state.filters.length > 0) {
      fabricObject.filters = [...state.filters];
      fabricObject.applyFilters();
    }
  }

  /**
   * 捕获图像数据
   * @param {Object} fabricObject Fabric对象
   * @returns {ImageData|null} 图像数据
   * @private
   */
  _captureImageData(fabricObject) {
    try {
      if (fabricObject._element && fabricObject._element.width && fabricObject._element.height) {
        const canvas = document.createElement("canvas");
        canvas.width = fabricObject._element.width;
        canvas.height = fabricObject._element.height;
        const ctx = canvas.getContext("2d");
        ctx.drawImage(fabricObject._element, 0, 0);
        return ctx.getImageData(0, 0, canvas.width, canvas.height);
      }
    } catch (error) {
      console.warn("无法捕获图像数据:", error);
    }
    return null;
  }

  /**
   * 更新图像数据缓存
   * @param {String} refId 引用ID
   * @param {ImageData} imageData 图像数据
   * @private
   */
  _updateImageDataCache(refId, imageData) {
    this.imageDataCache.set(refId, {
      data: imageData,
      timestamp: Date.now(),
      width: imageData.width,
      height: imageData.height,
    });
  }

  /**
   * 计算内存使用量（近似值）
   * @returns {Number} 内存使用量（字节）
   * @private
   */
  _calculateMemoryUsage() {
    let totalBytes = 0;

    // 计算ImageData缓存大小
    this.imageDataCache.forEach((cache) => {
      totalBytes += cache.width * cache.height * 4; // RGBA = 4 bytes per pixel
    });

    return totalBytes;
  }
}

/**
 * 创建单例引用管理器
 */
let liquifyReferenceManagerInstance = null;

export function getLiquifyReferenceManager() {
  if (!liquifyReferenceManagerInstance) {
    liquifyReferenceManagerInstance = new LiquifyReferenceManager();
  }
  return liquifyReferenceManagerInstance;
}
