<template>
  <div :id="elId" :class="`coalesce-bg ${snapped?'snapped':''}`">
    <div class="content--canvas"></div>
    <div :class="`cover_overlay ${overlayer} ${overlayerColor}`"
         :style="`--g_x:${w}px;--g_h:${h}px;`"></div>
    <slot class="coalesce_layer"></slot>
  </div>
</template>
<script>

import elementbase from "../mixins/tools/elementbase"
import { ColorTool, hexToRgb } from ".."
import {
  cos,
  randIn,
  sin,
  rand,
  TAU,
  TO_RAD,
  HALF_PI,
  fadeIn,
  fadeInOut,
  dist,
  angle,
  lerp
} from "../engines/three/wrapengine/mathlib"
export default {
  name: "BgCoalesce",
  mixins: [elementbase],
  // eslint-disable-next-line vue/require-prop-types
  props: ["backgroundColor", "elementColor"],
  mounted() {
    const particleCount = 700
    const particlePropCount = 9
    const particlePropsLength = particleCount * particlePropCount
    const baseTTL = 100
    const rangeTTL = 500
    const baseSpeed = 0.1
    const rangeSpeed = 1
    const baseSize = 2
    const rangeSize = 10
    const baseHue = 10
    const rangeHue = 100
    const noiseSteps = 2
    const xOff = 0.0025
    const yOff = 0.005
    const zOff = 0.0005
    const backgroundColor = this.backgroundColor

    let container
    let canvas
    let ctx
    let center
    let gradient
    let tick
    let particleProps
    let positions
    let velocities
    let lifeSpans
    let speeds
    let sizes
    let hues
    let customhue
    this.setup = () => {
      this.createCanvas()
      this.resize()
      this.initParticles()
      if (this.elementColor) {
        const r = hexToRgb(this.elementColor)
        customhue = new ColorTool(r.r, r.g, r.b, "spec")
      }
      this.draw()
    }

    this.initParticles = () => {
      tick = 0
      particleProps = new Float32Array(particlePropsLength)

      let i

      for (i = 0; i < particlePropsLength; i += particlePropCount) {
        this.initParticle(i)
      }
    }

    this.initParticle = (i) => {
      let theta, x, y, vx, vy, life, ttl, speed, size, hue

      x = rand(canvas.a.width)
      y = rand(canvas.a.height)
      theta = angle(x, y, center[0], center[1])
      vx = cos(theta) * 6
      vy = sin(theta) * 6
      life = 0
      ttl = baseTTL + rand(rangeTTL)
      speed = baseSpeed + rand(rangeSpeed)
      size = baseSize + rand(rangeSize)
      hue = baseHue + rand(rangeHue)

      particleProps.set([x, y, vx, vy, life, ttl, speed, size, hue], i)
    }/*
    this.initP = i => {
      let N, theta, x, y, vx, vy, life, ttl, speed, size, hue;

      x = rand(canvas.a.width);
      y = rand(canvas.a.height);
      N = randIn(3, 7);
      theta = angle(x, y, center[0], center[1]);
      vx = cos(theta) * 6;
      vy = sin(theta) * 6;
      life = 0;
      ttl = baseTTL + rand(rangeTTL);
      speed = baseSpeed + rand(rangeSpeed);
      size = baseSize + rand(rangeSize);
      hue = baseHue + rand(rangeHue);

      const cheq = new PolygonExPs3();
      cheq.atPosition(x, y);
      cheq.draw(ctx.a);

      particleProps.set([x, y, vx, vy, life, ttl, speed, size, hue], i);

    } */

    this.drawParticles = () => {
      let i

      for (i = 0; i < particlePropsLength; i += particlePropCount) {
        this.updateParticle(i)
      }
    }

    this.updateParticle = (i) => {
      const i2 = 1 + i
      const i3 = 2 + i
      const i4 = 3 + i
      const i5 = 4 + i
      const i6 = 5 + i
      const i7 = 6 + i
      const i8 = 7 + i
      const i9 = 8 + i
      let x, y, theta, vx, vy, life, ttl, speed, x2, y2, size, hue

      x = particleProps[i]
      y = particleProps[i2]
      theta = angle(x, y, center[0], center[1]) + 0.75 * HALF_PI
      vx = lerp(particleProps[i3], 2 * cos(theta), 0.05)
      vy = lerp(particleProps[i4], 2 * sin(theta), 0.05)
      life = particleProps[i5]
      ttl = particleProps[i6]
      speed = particleProps[i7]
      x2 = x + vx * speed
      y2 = y + vy * speed
      size = particleProps[i8]
      hue = particleProps[i9]

      this.drawParticle(x, y, theta, life, ttl, size, hue)

      life++

      particleProps[i] = x2
      particleProps[i2] = y2
      particleProps[i3] = vx
      particleProps[i4] = vy
      particleProps[i5] = life

      life > ttl && this.initParticle(i)
    }

    this.drawParticle = (x, y, theta, life, ttl, size, hue) => {
      const xRel = x - 0.5 * size
      const yRel = y - 0.5 * size
      ctx.a.save()
      ctx.a.lineCap = "round"
      ctx.a.lineWidth = 1
      if (this.elementColor) {
        ctx.a.strokeStyle =
            `hsla(${customhue.data().h},${customhue.data().s}%,${customhue.data().l}%,${fadeInOut(life, ttl)})`
      } else {
        ctx.a.strokeStyle = `hsla(${hue},100%,60%,${fadeInOut(life, ttl)})`
      }
      ctx.a.beginPath()
      ctx.a.translate(xRel, yRel)
      ctx.a.rotate(theta)
      ctx.a.translate(-xRel, -yRel)
      ctx.a.strokeRect(xRel, yRel, size, size)
      ctx.a.closePath()
      ctx.a.restore()
    }

    this.createCanvas = () => {
      container = document.querySelector(".content--canvas")
      canvas = {
        a: document.createElement("canvas"),
        b: document.createElement("canvas")
      }
      canvas.b.style = `
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
	`
      container.appendChild(canvas.b)
      ctx = {
        a: canvas.a.getContext("2d"),
        b: canvas.b.getContext("2d")
      }
      center = []
    }

    this.resize = () => {
      const { innerWidth, innerHeight } = window

      canvas.a.width = innerWidth
      canvas.a.height = innerHeight

      ctx.a.drawImage(canvas.b, 0, 0)

      canvas.b.width = innerWidth
      canvas.b.height = innerHeight

      ctx.b.drawImage(canvas.a, 0, 0)

      center[0] = 0.5 * canvas.a.width
      center[1] = 0.5 * canvas.a.height
    }

    this.renderGlow = () => {
      ctx.b.save()
      ctx.b.filter = "blur(8px) brightness(200%)"
      ctx.b.globalCompositeOperation = "lighter"
      ctx.b.drawImage(canvas.a, 0, 0)
      ctx.b.restore()

      ctx.b.save()
      ctx.b.filter = "blur(4px) brightness(200%)"
      ctx.b.globalCompositeOperation = "lighter"
      ctx.b.drawImage(canvas.a, 0, 0)
      ctx.b.restore()
    }

    this.render = () => {
      ctx.b.save()
      ctx.b.globalCompositeOperation = "lighter"
      ctx.b.drawImage(canvas.a, 0, 0)
      ctx.b.restore()
    }

    this.draw = () => {
      tick++

      ctx.a.clearRect(0, 0, canvas.a.width, canvas.a.height)

      ctx.b.fillStyle = backgroundColor
      ctx.b.fillRect(0, 0, canvas.a.width, canvas.a.height)

      this.drawParticles()
      this.renderGlow()
      this.render()
      if (!this.cancel) {
        window.requestAnimationFrame(this.draw)
      }
    }

    setTimeout(() => {
      this.setup()
    }, 100)

    window.addEventListener("resize", this.resize)
  },
  beforeDestroy() {
    this.cancel = true
    window.removeEventListener("resize", this.resize)
  }
}
</script>
