use crate::rendering::{self, MaterialUni};
use macroquad::prelude::*;
use macroquad::ui::{hash, Ui};

use strum::IntoEnumIterator;

// A struct that stores editable versions of all MaterialUni uniforms.
pub struct MaterialUi {
    pub render_normals_bool: bool,
    pub render_shadows_bool: bool,
    pub shadow_step_count: u32,
    pub shadow_step_size: u32,
    pub shadow_min_bias: f32,
    pub shadow_fac_bias: f32,
    pub shadow_max_bias: f32,
}

impl MaterialUi {
    pub fn new() -> Self {
        Self {
            render_normals_bool: false,
            render_shadows_bool: true,
            shadow_step_count: 3,
            shadow_step_size: 2,
            shadow_min_bias: 7.0,
            shadow_fac_bias: 4.0,
            shadow_max_bias: 100.0,
        }
    }
    pub fn apply(&self, material: &macroquad::prelude::Material) {
        use MaterialUni::*;
        material.set_uniform(RenderNormalsBool.as_str(), self.render_normals_bool as i32);
        material.set_uniform(RenderShadowsBool.as_str(), self.render_shadows_bool as i32);
        material.set_uniform(ShadowStepCount.as_str(), self.shadow_step_count as i32);
        material.set_uniform(ShadowStepSize.as_str(), self.shadow_step_size as i32);
        material.set_uniform(ShadowMinBias.as_str(), self.shadow_min_bias / 1000f32);
        material.set_uniform(ShadowFacBias.as_str(), self.shadow_fac_bias / 1000f32);
        material.set_uniform(ShadowMaxBias.as_str(), self.shadow_max_bias / 1000f32);
    }
}

impl MaterialUi {
    pub fn ui(&mut self, ui: &mut Ui) {
        use crate::rendering::MaterialUni::*;

        for uniform in rendering::MaterialUni::iter() {
            match uniform {
                RenderNormalsBool => {
                    ui.checkbox(
                        hash!("RenderNormalsBool"),
                        "Render Normals",
                        &mut self.render_normals_bool,
                    );
                }

                RenderShadowsBool => {
                    ui.checkbox(
                        hash!("RenderShadowsBool"),
                        "Render Shadows",
                        &mut self.render_shadows_bool,
                    );
                }

                ShadowStepCount => {
                    ui.drag(
                        hash!("ShadowStepCount"),
                        "Shadow Step Count",
                        Some((1, 15)),
                        &mut self.shadow_step_count,
                    );
                }

                ShadowStepSize => {
                    ui.drag(
                        hash!("ShadowStepSize"),
                        "Shadow Step Size",
                        Some((1, 15)),
                        &mut self.shadow_step_size,
                    );
                }

                ShadowMinBias => {
                    ui.slider(
                        hash!("ShadowMinBiasSlider"),
                        "1/1000th Min Bias",
                        0.0..1000.0, // min..max range
                        &mut self.shadow_min_bias,
                    );
                }

                ShadowFacBias => {
                    ui.slider(
                        hash!("ShadowFacBiasSlider"),
                        "1/1000th Fac Bias",
                        0.0..1000.0, // min..max range
                        &mut self.shadow_fac_bias,
                    );
                }

                ShadowMaxBias => {
                    ui.slider(
                        hash!("ShadowMaxBiasSlider"),
                        "1/1000th Max Bias",
                        0.0..200000.0, // min..max range
                        &mut self.shadow_max_bias,
                    );
                }

                _ => continue,
            }

            ui.separator();
        }
    }
}
