// particles2d.cm - Particle system factory
//
// Creates particle data objects that register with film2d
// Also provides emitter update logic

var film2d = use('film2d')
var random = use('random').random

var particles2d_proto = {
  type: 'particles',
  
  destroy: function() {
    film2d.unregister(this._id)
  }
}

// Emitter management
var emitters = {
  // Spawn a particle for an emitter
  spawn: function(emitter) {
    push(emitter.particles, {
      pos: {
        x: emitter.pos.x + (random() - 0.5) * emitter.spawn_area.width,
        y: emitter.pos.y + (random() - 0.5) * emitter.spawn_area.height
      },
      velocity: {
        x: emitter.velocity.x + (random() - 0.5) * emitter.velocity_var.x,
        y: emitter.velocity.y + (random() - 0.5) * emitter.velocity_var.y
      },
      life: emitter.life,
      time: 0,
      max_scale: emitter.scale + (random() - 0.5) * emitter.scale_var,
      scale: 0,
      color: {
        r: emitter.color.r,
        g: emitter.color.g + (random() - 0.5) * 0.3,
        b: emitter.color.b,
        a: 1
      }
    })
  },
  
  // Update an emitter and its particles
  update: function(emitter, dt) {
    // Spawn new particles
    if (emitter.rate > 0) {
      emitter.spawn_timer = (emitter.spawn_timer || 0) + dt
      var pp = 1 / emitter.rate
      while (emitter.spawn_timer > pp) {
        emitter.spawn_timer -= pp
        emitters.spawn(emitter)
      }
    }
    
    // Update existing particles
    for (var i = length(emitter.particles) - 1; i >= 0; i--) {
      var p = emitter.particles[i]
      p.time += dt
      p.pos.x += p.velocity.x * dt
      p.pos.y += p.velocity.y * dt
      
      // Scale animation
      var grow_for = emitter.grow_for || 0.3
      var shrink_for = emitter.shrink_for || 0.5
      if (p.time < grow_for) {
        p.scale = lerp(0, p.max_scale, p.time / grow_for)
      } else if (p.time > p.life - shrink_for) {
        p.scale = lerp(0, p.max_scale, (p.life - p.time) / shrink_for)
      } else {
        p.scale = p.max_scale
      }
      
      // Alpha fade
      var alpha = 1
      if (p.time > p.life * 0.7) {
        alpha = 1 - (p.time - p.life * 0.7) / (p.life * 0.3)
      }
      p.color.a = alpha
    }

    emitter.particles = filter(emitter.particles, p => p.time < p.life)
    
    // Sync to film2d if handle provided
    if (emitter.handle)
      emitter.handle.particles = emitter.particles
  },
  
  // Create an emitter config
  create: function(config) {
    return {
      pos: config.pos || {x: 0, y: 0},
      spawn_area: config.spawn_area || {width: 10, height: 10},
      velocity: config.velocity || {x: 0, y: 100},
      velocity_var: config.velocity_var || {x: 20, y: 20},
      life: config.life || 2,
      rate: config.rate || 10,
      scale: config.scale || 1,
      scale_var: config.scale_var || 0.3,
      grow_for: config.grow_for || 0.3,
      shrink_for: config.shrink_for || 0.5,
      color: config.color || {r: 1, g: 1, b: 1, a: 1},
      spawn_timer: 0,
      particles: [],
      handle: config.handle || null
    }
  }
}

function lerp(a, b, t) { return a + (b - a) * t }

// Factory function - auto-registers with film2d
var factory = function(props) {
  var defaults = {
    type: 'particles',
    pos: {x: 0, y: 0},
    image: null,
    width: 16,
    height: 16,
    plane: 'default',
    layer: 0,
    groups: [],
    particles: [],
    opacity: 1,
    tint: {r: 1, g: 1, b: 1, a: 1}
  }
  
  var data = object(defaults, props)

  var newparticles = meme(particles2d_proto, data)
  film2d.register(newparticles)
  return newparticles
}

// Attach emitter helpers to factory
factory.emitters = emitters

return factory