/* ============================================================
   particles.js — hit sparks, dust, projectiles, floating text
   ============================================================ */

class Particles {
  constructor() { this.list = []; this.texts = []; }

  spark(x, y, color, count = 10, speed = 6) {
    for (let i = 0; i < count; i++) {
      const a = Math.random() * Math.PI * 2;
      const s = Utils.rand(1, speed);
      this.list.push({
        x, y, vx: Math.cos(a) * s, vy: Math.sin(a) * s - 1,
        life: 1, decay: Utils.rand(0.03, 0.07),
        size: Utils.rand(2, 5), color, grav: 0.25, type: "spark",
      });
    }
  }

  dust(x, y, dir = 0) {
    for (let i = 0; i < 6; i++) {
      this.list.push({
        x, y, vx: Utils.rand(-1, 1) + dir * 2, vy: Utils.rand(-2.5, -0.5),
        life: 1, decay: 0.04, size: Utils.rand(3, 7),
        color: "rgba(180,190,210,0.6)", grav: 0.1, type: "dust",
      });
    }
  }

  ring(x, y, color) {
    this.list.push({ x, y, r: 4, life: 1, decay: 0.06, color, type: "ring" });
  }

  blood(x, y, dir) {
    for (let i = 0; i < 8; i++) {
      this.list.push({
        x, y, vx: Utils.rand(2, 7) * dir, vy: Utils.rand(-4, 1),
        life: 1, decay: 0.025, size: Utils.rand(2, 4),
        color: "#ff4040", grav: 0.4, type: "spark",
      });
    }
  }

  text(x, y, str, color = "#ffce3b", size = 28) {
    this.texts.push({ x, y, str, color, size, life: 1, vy: -1.1 });
  }

  // big expanding shockwave ring (ground pound / super impact)
  shockwave(x, y, color = "#fff", maxR = 160, lw = 8) {
    this.list.push({ x, y, r: 6, maxR, life: 1, decay: 0.04, color, type: "shock", lw });
  }

  // jagged lightning bolt from a->b
  lightning(x1, y1, x2, y2, color = "#bfe9ff") {
    const segs = 7, pts = [{ x: x1, y: y1 }];
    for (let i = 1; i < segs; i++) {
      const t = i / segs;
      pts.push({ x: Utils.lerp(x1, x2, t) + Utils.rand(-16, 16),
                 y: Utils.lerp(y1, y2, t) + Utils.rand(-16, 16) });
    }
    pts.push({ x: x2, y: y2 });
    this.list.push({ pts, life: 1, decay: 0.12, color, type: "bolt" });
  }

  // star-shaped flash sparkle
  star(x, y, color = "#fff", size = 26) {
    this.list.push({ x, y, size, life: 1, decay: 0.08, color, rot: Math.random() * 3, type: "star" });
  }

  // rising energy motes (charge / aura)
  ember(x, y, color) {
    this.list.push({
      x: x + Utils.rand(-22, 22), y, vx: Utils.rand(-0.6, 0.6),
      vy: Utils.rand(-3, -1.4), life: 1, decay: Utils.rand(0.02, 0.04),
      size: Utils.rand(2, 4), color, grav: -0.02, type: "spark",
    });
  }

  update() {
    for (let i = this.list.length - 1; i >= 0; i--) {
      const p = this.list[i];
      if (p.type === "ring") { p.r += 5; p.life -= p.decay; }
      else if (p.type === "shock") { p.r += (p.maxR - p.r) * 0.18 + 4; p.life -= p.decay; }
      else if (p.type === "bolt") { p.life -= p.decay; }
      else if (p.type === "star") { p.rot += 0.2; p.life -= p.decay; }
      else {
        p.x += p.vx; p.y += p.vy; p.vy += p.grav || 0;
        p.vx *= 0.98; p.life -= p.decay;
      }
      if (p.life <= 0) this.list.splice(i, 1);
    }
    for (let i = this.texts.length - 1; i >= 0; i--) {
      const t = this.texts[i];
      t.y += t.vy; t.vy *= 0.96; t.life -= 0.018;
      if (t.life <= 0) this.texts.splice(i, 1);
    }
  }

  draw(ctx) {
    for (const p of this.list) {
      ctx.globalAlpha = Math.max(0, p.life);
      if (p.type === "ring") {
        ctx.strokeStyle = p.color; ctx.lineWidth = 3;
        ctx.beginPath(); ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2); ctx.stroke();
      } else if (p.type === "shock") {
        ctx.strokeStyle = p.color; ctx.lineWidth = p.lw * p.life;
        ctx.beginPath(); ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2); ctx.stroke();
        ctx.globalAlpha *= 0.4;
        ctx.beginPath(); ctx.arc(p.x, p.y, p.r * 0.7, 0, Math.PI * 2); ctx.stroke();
      } else if (p.type === "bolt") {
        ctx.strokeStyle = p.color; ctx.lineWidth = 3;
        ctx.shadowColor = p.color; ctx.shadowBlur = 12;
        ctx.beginPath(); ctx.moveTo(p.pts[0].x, p.pts[0].y);
        for (let k = 1; k < p.pts.length; k++) ctx.lineTo(p.pts[k].x, p.pts[k].y);
        ctx.stroke(); ctx.shadowBlur = 0;
      } else if (p.type === "star") {
        ctx.save(); ctx.translate(p.x, p.y); ctx.rotate(p.rot);
        ctx.fillStyle = p.color; const s = p.size * p.life;
        ctx.beginPath();
        for (let k = 0; k < 8; k++) {
          const ang = (k / 8) * Math.PI * 2, rr = k % 2 ? s * 0.4 : s;
          ctx.lineTo(Math.cos(ang) * rr, Math.sin(ang) * rr);
        }
        ctx.closePath(); ctx.fill(); ctx.restore();
      } else {
        ctx.fillStyle = p.color;
        ctx.beginPath(); ctx.arc(p.x, p.y, p.size * p.life, 0, Math.PI * 2); ctx.fill();
      }
    }
    ctx.globalAlpha = 1;
    for (const t of this.texts) {
      ctx.globalAlpha = Math.max(0, t.life);
      ctx.font = `900 ${t.size}px "Trebuchet MS", sans-serif`;
      ctx.textAlign = "center";
      ctx.lineWidth = 5; ctx.strokeStyle = "#000";
      ctx.strokeText(t.str, t.x, t.y);
      ctx.fillStyle = t.color;
      ctx.fillText(t.str, t.x, t.y);
    }
    ctx.globalAlpha = 1;
  }
}

/* Beam — huge horizontal energy lance fired during a Super.
   Grows out from the caster, hits multiple times, then fades. */
class Beam {
  constructor(x, y, dir, owner) {
    this.x = x; this.y = y; this.dir = dir; this.owner = owner;
    this.len = 0; this.maxLen = 1300; this.h = 64;
    this.t = 0; this.life = 46; this.dead = false;
    this.damage = 4; this.hitTimer = 0;
  }
  get box() {
    const x = this.dir > 0 ? this.x : this.x - this.len;
    return { x, y: this.y - this.h / 2, w: this.len, h: this.h };
  }
  update() {
    this.t++; this.life--;
    this.len = Math.min(this.maxLen, this.len + 140);
    if (this.hitTimer > 0) this.hitTimer--;
    if (this.life <= 0) this.dead = true;
  }
  draw(ctx) {
    const col = this.owner.id === 1 ? "#39c6ff" : "#ff5a5a";
    const fade = Utils.clamp(this.life / 12, 0, 1);
    const x0 = this.x, x1 = this.x + this.dir * this.len;
    const pulse = (Math.sin(this.t * 0.6) * 0.2 + 1);
    ctx.save();
    ctx.globalAlpha = fade;
    // outer glow
    const grad = ctx.createLinearGradient(x0, 0, x1, 0);
    grad.addColorStop(0, "#fff");
    grad.addColorStop(0.2, col);
    grad.addColorStop(1, "rgba(0,0,0,0)");
    ctx.fillStyle = grad;
    ctx.shadowColor = col; ctx.shadowBlur = 40;
    const h = this.h * pulse;
    ctx.fillRect(Math.min(x0, x1), this.y - h / 2, this.len, h);
    // hot core
    ctx.shadowBlur = 0; ctx.globalAlpha = fade;
    ctx.fillStyle = "rgba(255,255,255,0.95)";
    ctx.fillRect(Math.min(x0, x1), this.y - h * 0.18, this.len, h * 0.36);
    ctx.restore();
  }
}

/* Projectile (fireball). Owned by a fighter, travels horizontally. */
class Projectile {
  constructor(x, y, dir, owner, ex = false) {
    this.x = x; this.y = y; this.dir = dir; this.owner = owner;
    this.ex = ex;
    this.vx = (ex ? 11 : 9) * dir;
    this.r = ex ? 30 : 18; this.dead = false; this.t = 0;
    this.damage = ex ? 14 : 8; this.hitstun = ex ? 28 : 22;
  }
  get box() { return { x: this.x - this.r, y: this.y - this.r, w: this.r * 2, h: this.r * 2 }; }
  update(fx) {
    this.x += this.vx; this.t++;
    // trailing embers
    if (fx && this.t % 2 === 0) fx.ember(this.x, this.y, this.owner.color);
    if (this.x < -60 || this.x > 1340) this.dead = true;
  }
  draw(ctx) {
    const pulse = 1 + Math.sin(this.t * 0.4) * 0.14;
    const col = this.owner.id === 1 ? "#39c6ff" : "#ff5a5a";
    ctx.save();
    // spinning energy ring for EX
    if (this.ex) {
      ctx.strokeStyle = "#fff"; ctx.lineWidth = 3; ctx.globalAlpha = 0.8;
      ctx.beginPath();
      ctx.ellipse(this.x, this.y, this.r * 1.5, this.r * 0.5,
                  this.t * 0.3, 0, Math.PI * 2);
      ctx.stroke();
    }
    // trailing glow
    for (let i = 4; i >= 0; i--) {
      ctx.globalAlpha = 0.15 * (5 - i);
      ctx.fillStyle = col;
      ctx.beginPath();
      ctx.arc(this.x - this.vx * i * 0.6, this.y, this.r * pulse * (1 - i * 0.11), 0, Math.PI * 2);
      ctx.fill();
    }
    ctx.globalAlpha = 1;
    ctx.shadowColor = col; ctx.shadowBlur = 20;
    const g = ctx.createRadialGradient(this.x, this.y, 2, this.x, this.y, this.r * pulse);
    g.addColorStop(0, "#fff");
    g.addColorStop(0.5, col);
    g.addColorStop(1, "rgba(0,0,0,0)");
    ctx.fillStyle = g;
    ctx.beginPath(); ctx.arc(this.x, this.y, this.r * pulse, 0, Math.PI * 2); ctx.fill();
    ctx.restore();
  }
}
