use super::*;
use crate::core::film::{CreateFilmBase, PixelSensor};
use crate::{Arena, FileLoc, ParameterDictionary};
use anyhow::{Result, anyhow};
use shared::Float;
use shared::core::camera::CameraTransform;
use shared::core::film::{FilmBase, SpectralFilm};
use shared::core::filter::FilterTrait;
use shared::spectra::{LAMBDA_MAX, LAMBDA_MIN};
use shared::utils::math::SquareMatrix;
use std::path::Path;


impl CreateFilm for SpectralFilm {
    fn create(
        params: &ParameterDictionary,
        exposure_time: Float,
        filter: Filter,
        _camera_transform: Option<CameraTransform>,
        loc: &FileLoc,
        _arena: &Arena,
    ) -> Result<Film> {
        // Missing default illuminant, use srgb
        let colorspace = params.color_space.as_ref().unwrap();
        let max_component_value = params.get_one_float("maxcomponentvalue", Float::INFINITY)?;
        let write_fp16 = params.get_one_bool("savefp16", true)?;
        let sensor = PixelSensor::create(params, colorspace.clone(), exposure_time, loc)?;
        let film_base = FilmBase::create(params, filter, Some(&sensor.device()), loc)?;

        let filename = params.get_one_string("filename", "pbrt.exr")?;
        if Path::new(&filename).extension() != Some("exr".as_ref()) {
            return Err(anyhow!("{}: EXR is the only format supported by GBufferFilm", loc).into());
        }

        let n_buckets = params.get_one_int("nbuckets", 16)? as usize;
        let lambda_min = params.get_one_float("lambdamin", LAMBDA_MIN as Float)?;
        let lambda_max = params.get_one_float("lambdamin", LAMBDA_MAX as Float)?;
        if lambda_min < LAMBDA_MIN as Float && lambda_max > LAMBDA_MAX as Float {
            return Err(anyhow!(
                "{}: PBRT must be recompiled with different values of LAMBDA_MIN and LAMBDA_MAX",
                loc
            ));
        }

        let film = SpectralFilm::new(
            &film_base,
            lambda_min,
            lambda_max,
            n_buckets,
            colorspace,
            max_component_value,
            write_fp16,
        );

        Ok(Film::Spectral(film))
    }
}
