/**
 * 混合液化管理器 - 根据模式智能选择算法
 */
export class HybridLiquifyManager {
  constructor(options = {}) {
    this.config = {
      gridSize: options.gridSize || 16,
      maxStrength: options.maxStrength || 200,
      smoothingIterations: options.smoothingIterations || 1,
      relaxFactor: options.relaxFactor || 0.1,
    };

    this.params = {
      size: 80,
      pressure: 0.8,
      distortion: 0,
      power: 0.8,
    };

    this.modes = {
      PUSH: "push",
      CLOCKWISE: "clockwise",
      COUNTERCLOCKWISE: "counterclockwise",
      PINCH: "pinch",
      EXPAND: "expand",
      CRYSTAL: "crystal",
      EDGE: "edge",
      RECONSTRUCT: "reconstruct",
    };

    // 定义哪些模式使用像素算法
    this.pixelModes = new Set([
      this.modes.CLOCKWISE,
      this.modes.COUNTERCLOCKWISE,
      this.modes.CRYSTAL,
      this.modes.EDGE,
    ]);

    // 定义哪些模式使用网格算法
    this.meshModes = new Set([
      this.modes.PUSH,
      this.modes.PINCH,
      this.modes.EXPAND,
      this.modes.RECONSTRUCT,
    ]);

    this.currentMode = this.modes.PUSH;
    this.originalImageData = null;
    this.currentImageData = null;
    this.mesh = null;
    this.initialized = false;
    this.canvas = document.createElement("canvas");
    this.ctx = this.canvas.getContext("2d");

    // 持续按压相关状态
    this.pressStartTime = 0;
    this.pressDuration = 0;
    this.accumulatedRotation = 0;
    this.accumulatedScale = 0;
    this.isHolding = false;
    this.continuousTimer = null;

    // 鼠标状态
    this.initialMouseX = 0;
    this.initialMouseY = 0;
    this.currentMouseX = 0;
    this.currentMouseY = 0;
    this.isDragging = false;
    this.dragDistance = 0;
  }

  // ...existing initialization methods...

  /**
   * 应用液化变形 - 智能选择算法
   */
  applyDeformation(x, y) {
    if (!this.initialized || !this.originalImageData) {
      return this.currentImageData;
    }

    // 更新鼠标位置
    this.currentMouseX = x;
    this.currentMouseY = y;

    const { size, pressure, power } = this.params;
    const radius = size;
    const strength = pressure * power;

    // 根据模式选择算法
    if (this.pixelModes.has(this.currentMode)) {
      return this._applyPixelDeformation(x, y, radius, strength);
    } else if (this.meshModes.has(this.currentMode)) {
      return this._applyMeshDeformation(x, y, radius, strength);
    }

    return this.currentImageData;
  }

  /**
   * 像素级液化算法 - 适用于旋转、水晶、边缘模式
   */
  _applyPixelDeformation(centerX, centerY, radius, strength) {
    const data = this.currentImageData.data;
    const width = this.currentImageData.width;
    const height = this.currentImageData.height;
    const tempData = new Uint8ClampedArray(data);

    const processRadius = Math.min(radius, Math.min(width, height) / 2);

    // 计算影响区域边界
    const minX = Math.max(0, Math.floor(centerX - processRadius));
    const maxX = Math.min(width, Math.ceil(centerX + processRadius));
    const minY = Math.max(0, Math.floor(centerY - processRadius));
    const maxY = Math.min(height, Math.ceil(centerY + processRadius));

    switch (this.currentMode) {
      case this.modes.CLOCKWISE:
      case this.modes.COUNTERCLOCKWISE:
        this._applyPixelRotation(
          tempData,
          data,
          width,
          height,
          centerX,
          centerY,
          processRadius,
          strength,
          this.currentMode === this.modes.CLOCKWISE
        );
        break;

      case this.modes.CRYSTAL:
        this._applyPixelCrystal(
          tempData,
          data,
          width,
          height,
          centerX,
          centerY,
          processRadius,
          strength
        );
        break;

      case this.modes.EDGE:
        this._applyPixelEdge(
          tempData,
          data,
          width,
          height,
          centerX,
          centerY,
          processRadius,
          strength
        );
        break;
    }

    return this.currentImageData;
  }

  /**
   * 像素级旋转算法
   */
  _applyPixelRotation(
    srcData,
    dstData,
    width,
    height,
    centerX,
    centerY,
    radius,
    strength,
    clockwise
  ) {
    // 计算旋转角度
    const timeFactor = Math.min(this.pressDuration / 1000, 5.0);
    const baseRotationSpeed = 0.015;
    const rotationAngle =
      (clockwise ? 1 : -1) * baseRotationSpeed * strength * (1.0 + timeFactor * 0.3);

    this.accumulatedRotation += rotationAngle;

    const minX = Math.max(0, Math.floor(centerX - radius));
    const maxX = Math.min(width, Math.ceil(centerX + radius));
    const minY = Math.max(0, Math.floor(centerY - radius));
    const maxY = Math.min(height, Math.ceil(centerY + radius));

    for (let y = minY; y < maxY; y++) {
      for (let x = minX; x < maxX; x++) {
        const dx = x - centerX;
        const dy = y - centerY;
        const distance = Math.sqrt(dx * dx + dy * dy);

        if (distance < radius && distance > 0.1) {
          // 距离衰减：内圈快，外圈慢
          const normalizedDistance = distance / radius;
          const falloff = Math.pow(1 - normalizedDistance, 2); // 二次衰减

          // 计算旋转后的源位置
          const angle = Math.atan2(dy, dx);
          const newAngle = angle + this.accumulatedRotation * falloff;

          const sourceX = centerX + Math.cos(newAngle) * distance;
          const sourceY = centerY + Math.sin(newAngle) * distance;

          // 双线性插值采样
          const color = this._bilinearSample(srcData, width, height, sourceX, sourceY);

          if (color) {
            const targetIdx = (y * width + x) * 4;
            dstData[targetIdx] = color[0];
            dstData[targetIdx + 1] = color[1];
            dstData[targetIdx + 2] = color[2];
            dstData[targetIdx + 3] = color[3];
          }
        }
      }
    }
  }

  /**
   * 像素级水晶效果
   */
  _applyPixelCrystal(srcData, dstData, width, height, centerX, centerY, radius, strength) {
    const timeFactor = Math.min(this.pressDuration / 1000, 3.0);
    const distortionStrength = strength * (1.0 + timeFactor * 0.5);

    const minX = Math.max(0, Math.floor(centerX - radius));
    const maxX = Math.min(width, Math.ceil(centerX + radius));
    const minY = Math.max(0, Math.floor(centerY - radius));
    const maxY = Math.min(height, Math.ceil(centerY + radius));

    for (let y = minY; y < maxY; y++) {
      for (let x = minX; x < maxX; x++) {
        const dx = x - centerX;
        const dy = y - centerY;
        const distance = Math.sqrt(dx * dx + dy * dy);

        if (distance < radius && distance > 0.1) {
          const normalizedDistance = distance / radius;
          const falloff = 1 - normalizedDistance * normalizedDistance;

          const angle = Math.atan2(dy, dx);
          const crystalRadius = normalizedDistance;

          // 多层波浪扭曲
          const wave1 = Math.sin(angle * 8 + this.pressDuration * 0.005) * 0.6;
          const wave2 = Math.cos(angle * 12 + this.pressDuration * 0.003) * 0.4;
          const waveAngle = angle + (wave1 + wave2) * distortionStrength * falloff;

          const radialMod =
            1 + Math.sin(crystalRadius * Math.PI * 2 + this.pressDuration * 0.002) * 0.3;
          const modDistance = distance * radialMod;

          const sourceX = centerX + Math.cos(waveAngle) * modDistance;
          const sourceY = centerY + Math.sin(waveAngle) * modDistance;

          const color = this._bilinearSample(srcData, width, height, sourceX, sourceY);

          if (color) {
            const targetIdx = (y * width + x) * 4;
            const factor = falloff * distortionStrength * 0.7;

            // 混合原始颜色和扭曲颜色
            const originalIdx = (y * width + x) * 4;
            dstData[targetIdx] = Math.round(
              srcData[originalIdx] * (1 - factor) + color[0] * factor
            );
            dstData[targetIdx + 1] = Math.round(
              srcData[originalIdx + 1] * (1 - factor) + color[1] * factor
            );
            dstData[targetIdx + 2] = Math.round(
              srcData[originalIdx + 2] * (1 - factor) + color[2] * factor
            );
            dstData[targetIdx + 3] = srcData[originalIdx + 3];
          }
        }
      }
    }
  }

  /**
   * 像素级边缘效果
   */
  _applyPixelEdge(srcData, dstData, width, height, centerX, centerY, radius, strength) {
    const timeFactor = Math.min(this.pressDuration / 1000, 2.5);
    const edgeStrength = strength * (1.0 + timeFactor * 0.4);

    const minX = Math.max(0, Math.floor(centerX - radius));
    const maxX = Math.min(width, Math.ceil(centerX + radius));
    const minY = Math.max(0, Math.floor(centerY - radius));
    const maxY = Math.min(height, Math.ceil(centerY + radius));

    for (let y = minY; y < maxY; y++) {
      for (let x = minX; x < maxX; x++) {
        const dx = x - centerX;
        const dy = y - centerY;
        const distance = Math.sqrt(dx * dx + dy * dy);

        if (distance < radius && distance > 0.1) {
          const normalizedDistance = distance / radius;
          const falloff = 1 - normalizedDistance * normalizedDistance;

          const angle = Math.atan2(dy, dx);
          const edgeRadius = normalizedDistance;

          const edgeWave =
            Math.sin(edgeRadius * Math.PI * 4 + this.pressDuration * 0.004) *
            Math.cos(angle * 6 + this.pressDuration * 0.002);
          const perpAngle = angle + Math.PI / 2;

          const edgeFactor = edgeWave * falloff * edgeStrength * 0.5;
          const offsetX = Math.cos(perpAngle) * edgeFactor;
          const offsetY = Math.sin(perpAngle) * edgeFactor;

          const sourceX = x + offsetX;
          const sourceY = y + offsetY;

          const color = this._bilinearSample(srcData, width, height, sourceX, sourceY);

          if (color) {
            const targetIdx = (y * width + x) * 4;
            dstData[targetIdx] = color[0];
            dstData[targetIdx + 1] = color[1];
            dstData[targetIdx + 2] = color[2];
            dstData[targetIdx + 3] = color[3];
          }
        }
      }
    }
  }

  /**
   * 双线性插值采样
   */
  _bilinearSample(data, width, height, x, y) {
    if (x < 0 || x >= width - 1 || y < 0 || y >= height - 1) {
      return null;
    }

    const x1 = Math.floor(x);
    const y1 = Math.floor(y);
    const x2 = x1 + 1;
    const y2 = y1 + 1;

    const fx = x - x1;
    const fy = y - y1;

    const getPixel = (px, py) => {
      const idx = (py * width + px) * 4;
      return [data[idx], data[idx + 1], data[idx + 2], data[idx + 3]];
    };

    const p1 = getPixel(x1, y1);
    const p2 = getPixel(x2, y1);
    const p3 = getPixel(x1, y2);
    const p4 = getPixel(x2, y2);

    return [
      Math.round(
        (1 - fx) * (1 - fy) * p1[0] +
          fx * (1 - fy) * p2[0] +
          (1 - fx) * fy * p3[0] +
          fx * fy * p4[0]
      ),
      Math.round(
        (1 - fx) * (1 - fy) * p1[1] +
          fx * (1 - fy) * p2[1] +
          (1 - fx) * fy * p3[1] +
          fx * fy * p4[1]
      ),
      Math.round(
        (1 - fx) * (1 - fy) * p1[2] +
          fx * (1 - fy) * p2[2] +
          (1 - fx) * fy * p3[2] +
          fx * fy * p4[2]
      ),
      Math.round(
        (1 - fx) * (1 - fy) * p1[3] +
          fx * (1 - fy) * p2[3] +
          (1 - fx) * fy * p3[3] +
          fx * fy * p4[3]
      ),
    ];
  }

  /**
   * 网格液化算法 - 适用于推拉、捏合、展开模式
   */
  _applyMeshDeformation(x, y, radius, strength) {
    if (!this.mesh) return this.currentImageData;

    // 使用现有的网格算法处理推拉、捏合、展开
    const mode = this.currentMode;
    const { distortion } = this.params;

    this._applyDeformation(x, y, radius, strength, mode, distortion);

    if (this.config.smoothingIterations > 0) {
      this._smoothMesh();
    }

    return this._applyMeshToImage();
  }

  // ...existing mesh methods...
}
