/**
 *@author liuhaixiao
 *@createTime 2018-12-20 11:55
 *@description 颜色随机变化
 */

const { PI, cos, sin, abs, sqrt, pow, round, random, atan2 } = Math;
const TAU = 2 * PI;
const rand = n => n * random();
const fadeInOut = (t, m) => {
  let hm = 0.5 * m;
  return abs((t + hm) % m - hm) / (hm);
};
var SimplexNoise = require('../noise.min');
const circleCount = 50;
const circlePropCount = 8;
const circlePropsLength = circleCount * circlePropCount;
const baseSpeed = 0.1;
const rangeSpeed = 1;
const baseTTL = 150;
const rangeTTL = 200;
const baseRadius = 100;
const rangeRadius = 200;
const rangeHue = 60;
const xOff = 0.0015;
const yOff = 0.0015;
const zOff = 0.0015;

let canvas;
let ctx;
let circleProps;
let simplex;
let baseHue;



export default class ColorRandom {

  random(min, max) {
    return Math.random() * (max - min) + min;
  }

  constructor(select) {
    this.oC = select;
    this.widthCanvas = this.oC.width;
    this.heightCanvas = this.oC.height;
    this.oGc = this.oC.getContext('2d');
  }

  initCircles() {
    circleProps = new Float32Array(circlePropsLength);
    simplex = new SimplexNoise();
    baseHue = 220;
    let i;
    for (i = 0; i < circlePropsLength; i += circlePropCount) {
      this.initCircle(i);
    }
  }

  initCircle(i) {
    let x, y, n, t, speed, vx, vy, life, ttl, radius, hue;

    x = rand(canvas.a.width);
    y = rand(canvas.a.height);
    n = simplex.noise3D(x * xOff, y * yOff, baseHue * zOff);
    t = rand(TAU);
    speed = baseSpeed + rand(rangeSpeed);
    vx = speed * cos(t);
    vy = speed * sin(t);
    life = 0;
    ttl = baseTTL + rand(rangeTTL);
    radius = baseRadius + rand(rangeRadius);
    hue = baseHue + n * rangeHue;

    circleProps.set([x, y, vx, vy, life, ttl, radius, hue], i);
  }

  updateCircles() {
    let i;
    baseHue++;
    for (i = 0; i < circlePropsLength; i += circlePropCount) {
      this.updateCircle(i);
    }
  }

  updateCircle(i) {
    let i2=1+i, i3=2+i, i4=3+i, i5=4+i, i6=5+i, i7=6+i, i8=7+i;
    let x, y, vx, vy, life, ttl, radius, hue;
    x = circleProps[i];
    y = circleProps[i2];
    vx = circleProps[i3];
    vy = circleProps[i4];
    life = circleProps[i5];
    ttl = circleProps[i6];
    radius = circleProps[i7];
    hue = circleProps[i8];
    this.drawCircle(x, y, life, ttl, radius, hue);
    life++;
    circleProps[i] = x + vx;
    circleProps[i2] = y + vy;
    circleProps[i5] = life;

    (this.checkBounds(x, y, radius) || life > ttl) && this.initCircle(i);
  }

  drawCircle(x, y, life, ttl, radius, hue) {
    ctx.a.save();
    ctx.a.fillStyle = `hsla(${hue},100%,30%,${fadeInOut(life,ttl)})`;
    ctx.a.beginPath();
    ctx.a.arc(x,y, radius, 0, TAU);
    ctx.a.fill();
    ctx.a.closePath();
    ctx.a.restore();
  }

  checkBounds(x, y, radius) {
    return (
      x < -radius ||
      x > canvas.a.width + radius ||
      y < -radius ||
      y > canvas.a.height + radius
    );
  }

  draw() {
    this.updateCircles();
    this.render();
    window.requestAnimationFrame(()=>{this.draw()});
  }

  render() {
    this.oGc.save();
    this.oGc.filter = 'blur(150px)';
    this.oGc.drawImage(canvas.a, 0, 0);
    this.oGc.restore();
  }

  create() {
    canvas = {
      a: document.createElement('canvas'),
      b: this.oC
    };
    canvas.a.width = this.widthCanvas
    canvas.a.height = this.heightCanvas
    this.oGc.style = `
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
	`;
    ctx = {
      a: canvas.a.getContext('2d'),
      b: canvas.b.getContext('2d')
    };
  }

  setup() {
    this.create();
    this.initCircles();
    this.draw();
  }

  process() {

    this.setup()
  }
}
