use super::*;
use crate::core::film::{CreateFilmBase, PixelSensor};
use crate::utils::containers::Array2D;
use anyhow::{Result, anyhow};
use shared::core::film::{FilmBase, GBufferFilm};
use shared::core::filter::FilterTrait;
use shared::spectra::RGBColorSpace;
use shared::utils::AnimatedTransform;
use std::path::Path;


impl CreateFilm for GBufferFilm {
    fn create(
        params: &ParameterDictionary,
        exposure_time: Float,
        filter: Filter,
        camera_transform: Option<CameraTransform>,
        loc: &FileLoc,
        _arena: &Arena,
    ) -> Result<Film> {
        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 coords_system = params.get_one_string("coordinatesystem", "camera")?;
        let mut apply_inverse = false;
        let camera_transform =
            camera_transform.ok_or_else(|| anyhow!("GBufferFilm requires a camera_transform"))?;
        let output_from_render = if coords_system == "camera" {
            apply_inverse = true;
            camera_transform.render_from_camera
        } else if coords_system == "world" {
            AnimatedTransform::from_transform(&camera_transform.world_from_render)
        } else {
            return Err(anyhow!(
                "{}: unknown coordinate system for GBufferFilm. (Expecting camera 
                  or world",
                loc
            )
            .into());
        };

        let film = GBufferFilm::new(
            &film_base,
            &output_from_render,
            apply_inverse,
            colorspace,
            max_component_value,
            write_fp16,
        );

        Ok(Film::GBuffer(film))
    }
}
