/**
 * 爆破动画
 */

import { generateSimilarColors } from "../base/utils";


/**
 * 爆破微粒
 */
class Particle {
  ctx: CanvasRenderingContext2D;
  x: number;
  y: number;
  r: number;
  dx: number;
  dy: number;
  color: string;
  a: number;

  /**
   * 
   * @param ctx 
   * @param x 初始坐标x
   * @param y 初始坐标y
   * @param r 颗粒大小半径
   * @param dx 每帧移动x坐标距离
   * @param dy 每帧移动y坐标距离
   * @param color 颜色
   */
  constructor(ctx: CanvasRenderingContext2D, x: number, y: number, r: number, dx: number, dy: number, color: string) {
    this.x = x;
    this.y = y;
    this.r = r;
    this.dx = dx;
    this.dy = dy;
    this.color = color;
    this.a = 1;
    this.ctx = ctx;
  }

  draw() {
    let ctx = this.ctx;

    ctx.save();
    ctx.globalAlpha = this.a;
    ctx.fillStyle = this.color;

    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, false);
    ctx.fill();

    ctx.restore();
  }

  update() {
    this.draw();
    this.a -= 1 / 120;
    this.x += this.dx;
    this.y += this.dy;
  }
}

export default class Explosion {
  canvas: HTMLCanvasElement;
  ctx: CanvasRenderingContext2D;
  onend: Function;
  particles: Particle[] = [];

  constructor(canvas: HTMLCanvasElement, color: string, particleNum: number, onend: Function) {
    this.canvas = canvas;
    this.canvas.width = Math.floor(this.canvas.offsetWidth * window.devicePixelRatio);
    this.canvas.height = Math.floor(this.canvas.offsetHeight * window.devicePixelRatio);
    this.ctx = this.canvas.getContext("2d")!;
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    this.initParticles(color, particleNum);
    this.onend = onend;
  }


  /**
   * 用requestAnimationFrame试试==>果然效果好多了，而且在低端机上效果明显
   */
  explode() {
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    this.particles.forEach((particle, i) => {
      if (particle.a <= 0) {
        this.particles.splice(i, 1);
      } else {
        particle.update();
      }
    })

    if (this.particles.length == 0) {
      this.onend && this.onend();
      return;
    }
    requestAnimationFrame(this.explode.bind(this));
  }

  private initParticles(color: string, particleNum: number) {
    let colors = generateSimilarColors(color, particleNum);
    for (let i = 0; i < particleNum; i++) {
      let x = this.canvas.width / 2 + (Math.random() - 0.5) * (Math.random() * 10);
      let y = this.canvas.height / 2 + (Math.random() - 0.5) * (Math.random() * 10);
      let r = (Math.floor(Math.random() * 4) + 1) * window.devicePixelRatio;
      let dx = (Math.random() - 0.5) * (Math.random() * 8) * window.devicePixelRatio;
      let dy = (Math.random() - 0.5) * (Math.random() * 6) * window.devicePixelRatio;
      let c = colors[i];
      let particle = new Particle(this.ctx, x, y, r, dx, dy, c);
      this.particles.push(particle);
    }
  }
}