use crate::Arena;
use shared::core::light::{Light, LightTrait};
use shared::lights::sampler::PowerLightSampler;
use shared::utils::sampling::AliasTable;
use shared::spectra::{SampledSpectrum, SampledWavelengths};
use std::collections::HashMap;
use std::sync::Arc;

pub struct PowerSamplerHost {
    pub lights: Vec<Arc<Light>>,
    pub light_to_index: HashMap<usize, usize>,
    pub alias_table: AliasTable,
}

impl PowerSamplerHost {
    pub fn new(lights: &[Arc<Light>]) -> Self {
        if lights.is_empty() {
            return Self {
                lights: Vec::new(),
                light_to_index: HashMap::new(),
                alias_table: AliasTable::new(&[]),
            };
        }

        let mut lights_vec = Vec::with_capacity(lights.len());
        let mut light_to_index = HashMap::with_capacity(lights.len());
        let mut light_power = Vec::with_capacity(lights.len());

        let lambda = SampledWavelengths::sample_visible(0.5);

        for (i, light) in lights.iter().enumerate() {
            lights_vec.push(light.clone());

            let ptr = Arc::as_ptr(light) as usize;
            light_to_index.insert(ptr, i);

            let phi = SampledSpectrum::safe_div(&light.phi(lambda), &lambda.pdf());
            light_power.push(phi.average());
        }

        let alias_table = AliasTable::new(&light_power);

        Self {
            lights: lights_vec,
            light_to_index,
            alias_table,
        }
    }
    // pub fn to_device(&self, arena: &Arena) -> PowerLightSampler {
    //     let device_lights: Vec<Light> = self.lights.iter().map(|l| (**l).clone()).collect();
    //     let (lights_ptr, _) = arena.alloc_slice(&device_lights);
    //     let alias_device = self.alias_table.to_device(arena);
    //
    //     PowerLightSampler {
    //         lights: lights_ptr,
    //         lights_len: self.lights.len() as u32,
    //         alias_table: alias_device,
    //     }
    // }
}
