use crate::acceleration_structure::{triangle_bvh::TriangleBVH, AccelerationStructureScene};
use ray_tracing_core::prelude::*;
use ray_tracing_material::{
    iridescent::Iridescent,
    microfacet::{BeckmannDistribution, Microfacet},
    mirror::Mirror,
};
use std::{collections::HashMap, fmt::Debug, sync::Arc};

pub enum ExampleSceneEnum<R: Rng> {
    AccelerationStructureScene(AccelerationStructureScene<TriangleBVH<u32>, R>),
    TriangleBVH(crate::triangle_bvh::TriangleBVH<R>),
    BasicScene(crate::basic_scene::BasicScene<Arc<dyn Material<R>>>),
}

pub trait ExampleScene<R: Rng> {
    fn get_scene(&self) -> ExampleSceneEnum<R>;

    fn get_camera_pos(&self) -> Pos3;

    fn get_camera_look_at(&self) -> Pos3;

    fn get_camera_up(&self) -> Dir3;

    fn get_horizontal_fov(&self) -> Float;
}

pub fn example_scenes<R: Rng + Debug + 'static>() -> HashMap<&'static str, Box<dyn ExampleScene<R>>>
{
    let mut map: HashMap<&str, Box<dyn ExampleScene<R>>> = HashMap::new();
    map.insert("basic_cornel", Box::new(basic_cornell::BasicCornell::new()));
    map.insert("cornel2", Box::new(cornell2::Cornell2::new()));
    let color = Color::new(0.2, 0.2, 0.9);
    let material = Microfacet::new(BeckmannDistribution::new(0.01), color);
    map.insert(
        "stanford_dragon_microfacet",
        Box::new(stanford_dragon::StanfordDragon::new(material)),
    );
    let material = Iridescent::new(250.0, 250.0, 1.0, 1.5, 20);
    map.insert(
        "stanford_dragon_iridescent",
        Box::new(stanford_dragon::StanfordDragon::new(material)),
    );
    let material = Iridescent::new(0.9 * 988.0, 0.1 * 988.0, 1.0, 1.5, 20);
    map.insert(
        "stanford_dragon_iridescent2",
        Box::new(stanford_dragon::StanfordDragon::new(material)),
    );
    let material = Mirror::new(Color::white());
    map.insert(
        "stanford_dragon_mirror",
        Box::new(stanford_dragon::StanfordDragon::new(material)),
    );
    map.insert(
        "stanford_dragon_as",
        Box::new(stanford_dragon_as::StanfordDragon::new()),
    );
    map.insert("mis_test", Box::new(mis_test::MISTest::new()));

    // let material = Iridescent::new(250.0, 250.0, 1.0, 1.3, 20);
    let material = Iridescent::new(0.9 * 988.0, 0.1 * 988.0, 1.0, 1.5, 20);
    map.insert("sphere", Box::new(sphere::SphereScene::new(material)));

    map.insert(
        "presentation",
        Box::new(presentation_title_image::Presentation::new()),
    );
    map
}

pub mod basic_cornell;
pub mod cornell2;
pub mod mis_test;
pub mod presentation_title_image;
pub mod sphere;
pub mod stanford_dragon;
pub mod stanford_dragon_as;
