import { BUBBLE_RADIUS, BUBBLE_COLORS } from '../bubble/bubble';

// ─── 圆形粒子 ─────────────────────────────────────────────────────────────────

class CircleParticle {
  constructor(x, y, colorHex, vx, vy, radius, maxLife) {
    this.x = x;
    this.y = y;
    this.color = colorHex;
    this.vx = vx;
    this.vy = vy;
    this.radius = radius;
    this.alpha = 1;
    this.life = 0;
    this.maxLife = maxLife;
    this.alive = true;
  }

  update() {
    this.vx *= 0.92;
    this.vy = this.vy * 0.92 + 0.2;
    this.x += this.vx;
    this.y += this.vy;
    this.life++;
    this.alpha = Math.max(0, 1 - this.life / this.maxLife);
    this.radius = Math.max(0.5, this.radius * 0.97);
    if (this.life >= this.maxLife) this.alive = false;
  }
}

// ─── 火花线条粒子 ────────────────────────────────────────────────────────────

class SparkParticle {
  constructor(x, y, colorHex, vx, vy) {
    this.x = x;
    this.y = y;
    this.color = colorHex;
    this.vx = vx;
    this.vy = vy;
    this.prevX = x;
    this.prevY = y;
    this.alpha = 1;
    this.life = 0;
    this.maxLife = 18 + Math.floor(Math.random() * 14);
    this.alive = true;
    this.isSpark = true; // 标记类型，用于批量渲染
  }

  update() {
    this.prevX = this.x;
    this.prevY = this.y;
    this.vx *= 0.88;
    this.vy = this.vy * 0.88 + 0.15;
    this.x += this.vx;
    this.y += this.vy;
    this.life++;
    this.alpha = Math.max(0, 1 - this.life / this.maxLife);
    if (this.life >= this.maxLife) this.alive = false;
  }
}

// ─── 冲击波圆环 ──────────────────────────────────────────────────────────────

class ShockRing {
  constructor(x, y, colorHex, delay = 0) {
    this.x = x;
    this.y = y;
    this.color = colorHex;
    this.r = BUBBLE_RADIUS * 0.2;
    this.maxR = BUBBLE_RADIUS * 2.4;
    this.life = -delay;
    this.maxLife = 24;
    this.alpha = 0;
    this.alive = true;
  }

  update() {
    this.life++;
    if (this.life <= 0) return;
    const t = this.life / this.maxLife;
    this.r = BUBBLE_RADIUS * 0.2 + (this.maxR - BUBBLE_RADIUS * 0.2) * t;
    this.alpha = 0.9 * (1 - t);
    if (this.life >= this.maxLife) this.alive = false;
  }
}

// ─── 单颗泡泡爆炸 ─────────────────────────────────────────────────────────────

export default class Explosion {
  /**
   * @param {number} x 爆炸中心 x
   * @param {number} y 爆炸中心 y
   * @param {number} color 泡泡颜色索引 1-6
   * @param {boolean} isFloating 是否为悬空掉落（较小效果）
   */
  constructor(x, y, color, isFloating = false) {
    this.alive = true;
    this.particles = [];
    this.rings = [];

    const colorHex = BUBBLE_COLORS[color] || '#ffffff';
    const R = BUBBLE_RADIUS;

    // ── 闪光帧数
    this.flashLife = isFloating ? 4 : 10;
    this._x = x;
    this._y = y;
    this._colorHex = colorHex;

    // ── 圆形粒子
    const circleCount = isFloating ? 7 : 12;
    for (let i = 0; i < circleCount; i++) {
      const angle = (i / circleCount) * Math.PI * 2 + (Math.random() - 0.5) * 0.8;
      const speed = isFloating
        ? (1.5 + Math.random() * 3)
        : (2.5 + Math.random() * 5);
      const vx = Math.cos(angle) * speed;
      // 掉落效果往下偏，爆炸效果四散
      const vy = isFloating
        ? (Math.sin(angle) * speed * 0.4 + 1.5)
        : Math.sin(angle) * speed;
      const radius = R * (isFloating ? 0.2 : 0.18 + Math.random() * 0.28);
      const maxLife = 25 + Math.floor(Math.random() * 20);
      this.particles.push(new CircleParticle(x, y, colorHex, vx, vy, radius, maxLife));
    }

    // ── 白色 & 黄色小圆粒子（高光碎片）
    const glintCount = isFloating ? 2 : 5;
    for (let i = 0; i < glintCount; i++) {
      const angle = Math.random() * Math.PI * 2;
      const speed = 3 + Math.random() * 4;
      const glintColor = Math.random() < 0.5 ? '#ffffff' : '#ffe566';
      this.particles.push(
        new CircleParticle(x, y, glintColor,
          Math.cos(angle) * speed, Math.sin(angle) * speed,
          R * 0.12, 18 + Math.floor(Math.random() * 12))
      );
    }

    // ── 火花线条粒子
    const sparkCount = isFloating ? 2 : 5;
    for (let i = 0; i < sparkCount; i++) {
      const angle = Math.random() * Math.PI * 2;
      const speed = 5 + Math.random() * 7;
      const sparkColor = i % 2 === 0 ? '#ffffff' : colorHex;
      this.particles.push(
        new SparkParticle(x, y, sparkColor,
          Math.cos(angle) * speed, Math.sin(angle) * speed)
      );
    }

    // ── 冲击波圆环（主消除才有，掉落没有）
    if (!isFloating) {
      this.rings.push(new ShockRing(x, y, colorHex, 0));
      // 第二圈稍晚一点，白色，营造层次感
      this.rings.push(new ShockRing(x, y, '#ffffff', 5));
    }
  }

  update() {
    if (this.flashLife > 0) this.flashLife--;

    for (const p of this.particles) {
      if (p.alive) p.update();
    }
    for (const r of this.rings) {
      if (r.alive) r.update();
    }

    if (
      this.flashLife <= 0 &&
      this.particles.every(p => !p.alive) &&
      this.rings.every(r => !r.alive)
    ) {
      this.alive = false;
    }
  }

  render(ctx) {
    // ── 闪光光晕（用简单实心圆代替每帧创建 radialGradient，大幅减少 native 内存开销）
    if (this.flashLife > 0) {
      const t = this.flashLife / 10;
      ctx.save();
      ctx.globalAlpha = t * 0.6;
      ctx.fillStyle = '#ffffff';
      ctx.beginPath();
      ctx.arc(this._x, this._y, BUBBLE_RADIUS * 0.8, 0, Math.PI * 2);
      ctx.fill();
      ctx.globalAlpha = t * 0.4;
      ctx.fillStyle = this._colorHex;
      ctx.beginPath();
      ctx.arc(this._x, this._y, BUBBLE_RADIUS * 1.4, 0, Math.PI * 2);
      ctx.fill();
      ctx.restore();
    }

    // ── 冲击波圆环（批量渲染，一次 save/restore）
    ctx.save();
    ctx.lineWidth = 2.5;
    for (const r of this.rings) {
      if (!r.alive || r.alpha <= 0 || r.life <= 0) continue;
      ctx.globalAlpha = r.alpha;
      ctx.strokeStyle = r.color;
      ctx.beginPath();
      ctx.arc(r.x, r.y, r.r, 0, Math.PI * 2);
      ctx.stroke();
    }
    ctx.restore();

    // ── 粒子批量渲染（圆形粒子 + 火花线条，一次 save/restore）
    ctx.save();
    for (const p of this.particles) {
      if (!p.alive || p.alpha <= 0) continue;
      ctx.globalAlpha = p.alpha;
      if (p.isSpark) {
        // 火花线条
        ctx.strokeStyle = p.color;
        ctx.lineWidth = 1.8;
        ctx.lineCap = 'round';
        ctx.beginPath();
        ctx.moveTo(p.x, p.y);
        ctx.lineTo(p.prevX, p.prevY);
        ctx.stroke();
      } else {
        // 圆形粒子
        ctx.fillStyle = p.color;
        ctx.beginPath();
        ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2);
        ctx.fill();
      }
    }
    ctx.restore();
  }
}
