//! GPU-side emitter management.

use dreamwell_engine::physics::EmitterDescriptor;

/// GPU-side emitter state.
pub struct GpuEmitter {
    pub id: u64,
    pub descriptor: EmitterDescriptor,
    pub position: [f32; 3],
    pub seed: u64,
    pub active: bool,
    pub time_accumulator: f32,
    pub particles_spawned: u64,
}

/// Pool of active emitters.
pub struct EmitterPool {
    emitters: Vec<GpuEmitter>,
    next_id: u64,
}

impl EmitterPool {
    pub fn new() -> Self {
        Self {
            emitters: Vec::new(),
            next_id: 1,
        }
    }

    pub fn add(&mut self, desc: &EmitterDescriptor, position: [f32; 3], seed: u64) -> u64 {
        let id = self.next_id;
        self.next_id += 1;
        self.emitters.push(GpuEmitter {
            id,
            descriptor: desc.clone(),
            position,
            seed,
            active: true,
            time_accumulator: 0.0,
            particles_spawned: 0,
        });
        id
    }

    pub fn remove(&mut self, id: u64) {
        self.emitters.retain(|e| e.id != id);
    }

    pub fn active_emitters(&self) -> &[GpuEmitter] {
        &self.emitters
    }

    pub fn active_emitters_mut(&mut self) -> &mut [GpuEmitter] {
        &mut self.emitters
    }

    pub fn estimated_alive(&self) -> u32 {
        self.emitters
            .iter()
            .filter(|e| e.active)
            .map(|e| e.descriptor.spawn.max_live)
            .sum()
    }

    pub fn len(&self) -> usize {
        self.emitters.len()
    }

    pub fn is_empty(&self) -> bool {
        self.emitters.is_empty()
    }
}

impl Default for EmitterPool {
    fn default() -> Self {
        Self::new()
    }
}
