var color = use('color')
var graphics = use('graphics')
var transform = use('transform')

var ex = {}

ex.emitters = new Set()

ex.garbage = function()
{
  ex.emitters.delete(this)
}

ex.update = function(dt)
{
  for (var e of ex.emitters)
    try { e.step(dt) } catch(e) { log.error(e) }
}

ex.step_hook = function(p)
{
  if (p.time < this.grow_for) {
    var s = Math.lerp(0, this.scale, p.time / this.grow_for);
    p.transform.scale = s;
  } else if (p.time > p.life - this.shrink_for) {
    var s = Math.lerp(0, this.scale, (p.life - p.time) / this.shrink_for);
    p.transform.scale = s;
  } else p.transform.scale = [this.scale, this.scale, this.scale];
}

ex.step = function(dt)
{
  // update spawning particles
  if (this.on && this.pps > 0) {
    this.spawn_timer += dt;
    var pp = 1 / this.pps;
    while (this.spawn_timer > pp) {
      this.spawn_timer -= pp;
      this.spawn();
    }
  }

  // update all particles
  for (var p of this.particles) {
    p.time += dt;
    p.transform.move(p.body.velocity?.scale(dt));
    this.step_hook?.(p);

    if (this.kill_hook?.(p) || p.time >= p.life) {
      this.die_hook?.(p);
      this.dead.push(p);
      this.particles.delete(p);
    }
  }
}

ex.burst = function(count,t)
{
  for (var i = 0; i < count; i++) this.spawn(t)
}

ex.spawn = function(t)
{
  t ??= this.transform

  var par = this.dead.shift()
  if (par) {
    par.transform.unit()
    par.transform.pos = t.pos;
    par.transform.scale = this.scale;
    this.particles.push(par);
    par.time = 0;
    this.spawn_hook?.(par);
    par.life = this.life;
    return;
  }

  par = {
    transform: new transform,
    life: this.life,
    time: 0,
    color: this.color,
    body:{},
  }

  par.transform.scale = this.scale
  this.particles.push(par)
  this.spawn_hook(par)
}

ex.stat = function()
{
  var stat = {};
  stat.emitters = emitters.length;
  var particles = 0;
  for (var e of emitters) particles += e.particles.length;
  stat.particles = particles;
  return stat;
}

ex.life = 10
ex.scale = 1
ex.grow_for = 0
ex.spawn_timer = 0
ex.pps = 0
ex.color = color.white

ex.draw = function()
{
/*  var diff = graphics.texture(this.diffuse)
  if (!diff) throw new Error("emitter does not have a proper diffuse texture")

  var mesh = graphics.make_sprite_mesh(this.particles)
  if (mesh.num_indices == 0) return
  render.queue({
    type:'geometry',
    mesh,
    image:diff,
    pipeline,
    first_index:0,
    num_indices:mesh.num_indices
  })
*/
}

return ex

---

this.particles = []
this.dead = []

this.transform = this.overling.transform

$.emitters.add(this)
