use super::ComponentInspector;
use nightshade::prelude::*;

pub struct CameraInspector;

impl ComponentInspector for CameraInspector {
    fn name(&self) -> &str {
        "Camera"
    }

    fn has_component(&self, world: &World, entity: Entity) -> bool {
        world.entity_has_camera(entity)
    }

    fn add_component(&self, world: &mut World, entity: Entity) {
        world.set_camera(entity, Camera::default());
    }

    fn remove_component(&self, world: &mut World, entity: Entity) {
        world.remove_camera(entity);
    }

    fn ui(&mut self, world: &mut World, entity: Entity, ui: &mut egui::Ui) {
        if let Some(camera) = world.get_camera_mut(entity) {
            let is_perspective = matches!(camera.projection, Projection::Perspective(_));

            ui.horizontal(|ui| {
                ui.label("Projection:");
                if ui.selectable_label(is_perspective, "Perspective").clicked() && !is_perspective {
                    camera.projection = Projection::Perspective(PerspectiveCamera::default());
                }
                if ui
                    .selectable_label(!is_perspective, "Orthographic")
                    .clicked()
                    && is_perspective
                {
                    camera.projection = Projection::Orthographic(OrthographicCamera::default());
                }
            });

            ui.separator();

            match &mut camera.projection {
                Projection::Perspective(perspective) => {
                    ui.label("Field of View:");
                    let mut fov_degrees = perspective.y_fov_rad.to_degrees();
                    if ui
                        .add(egui::Slider::new(&mut fov_degrees, 1.0..=120.0).suffix("°"))
                        .changed()
                    {
                        perspective.y_fov_rad = fov_degrees.to_radians();
                    }

                    ui.label("Near Plane:");
                    ui.add(egui::DragValue::new(&mut perspective.z_near).speed(0.01));

                    ui.horizontal(|ui| {
                        let mut has_far = perspective.z_far.is_some();
                        if ui.checkbox(&mut has_far, "Far Plane:").changed() {
                            perspective.z_far = if has_far { Some(1000.0) } else { None };
                        }

                        if let Some(ref mut z_far) = perspective.z_far {
                            ui.add(egui::DragValue::new(z_far).speed(1.0));
                        }
                    });
                }
                Projection::Orthographic(orthographic) => {
                    ui.label("Width:");
                    ui.add(egui::DragValue::new(&mut orthographic.x_mag).speed(0.1));

                    ui.label("Height:");
                    ui.add(egui::DragValue::new(&mut orthographic.y_mag).speed(0.1));

                    ui.label("Near Plane:");
                    ui.add(egui::DragValue::new(&mut orthographic.z_near).speed(0.1));

                    ui.label("Far Plane:");
                    ui.add(egui::DragValue::new(&mut orthographic.z_far).speed(1.0));
                }
            }
        }
    }
}
