use super::{ComponentInspector, EditorContext};
use nightshade::prelude::*;

pub struct TransformInspector {
    uniform_scaling: bool,
}

impl Default for TransformInspector {
    fn default() -> Self {
        Self {
            uniform_scaling: true,
        }
    }
}

impl ComponentInspector for TransformInspector {
    fn name(&self) -> &str {
        "Transform"
    }

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

    fn add_component(&self, world: &mut World, entity: Entity) {
        world.set_local_transform(entity, LocalTransform::default());
        world.set_global_transform(entity, GlobalTransform::default());
        mark_local_transform_dirty(world, entity);
    }

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

    fn ui(
        &mut self,
        world: &mut World,
        entity: Entity,
        ui: &mut egui::Ui,
        editor: &mut EditorContext,
    ) {
        if let Some(global_transform) = world.get_global_transform(entity) {
            let global_position = global_transform.translation();
            ui.label("Global Position (Read-only):");
            ui.horizontal(|ui| {
                ui.label(format!("X: {:.2}", global_position.x));
                ui.label(format!("Y: {:.2}", global_position.y));
                ui.label(format!("Z: {:.2}", global_position.z));
            });
            ui.separator();
        }

        if let Some(local_transform) = world.get_local_transform_mut(entity) {
            let initial_transform = *local_transform;
            let mut changed = false;
            let mut any_drag_started = false;
            let mut any_drag_released = false;

            ui.label("Local Position:");
            ui.horizontal(|ui| {
                ui.label("X:");
                let response =
                    ui.add(egui::DragValue::new(&mut local_transform.translation.x).speed(0.1));
                changed |= response.changed();
                any_drag_started |= response.drag_started();
                any_drag_released |= response.drag_stopped();

                ui.label("Y:");
                let response =
                    ui.add(egui::DragValue::new(&mut local_transform.translation.y).speed(0.1));
                changed |= response.changed();
                any_drag_started |= response.drag_started();
                any_drag_released |= response.drag_stopped();

                ui.label("Z:");
                let response =
                    ui.add(egui::DragValue::new(&mut local_transform.translation.z).speed(0.1));
                changed |= response.changed();
                any_drag_started |= response.drag_started();
                any_drag_released |= response.drag_stopped();
            });

            ui.label("Local Scale:");
            ui.horizontal(|ui| {
                if self.uniform_scaling {
                    ui.label("XYZ:");
                    let mut uniform_scale = local_transform.scale.x;
                    let response = ui.add(egui::DragValue::new(&mut uniform_scale).speed(0.01));
                    if response.changed() {
                        local_transform.scale =
                            Vec3::new(uniform_scale, uniform_scale, uniform_scale);
                        changed = true;
                    }
                    any_drag_started |= response.drag_started();
                    any_drag_released |= response.drag_stopped();
                } else {
                    ui.label("X:");
                    let response =
                        ui.add(egui::DragValue::new(&mut local_transform.scale.x).speed(0.01));
                    changed |= response.changed();
                    any_drag_started |= response.drag_started();
                    any_drag_released |= response.drag_stopped();

                    ui.label("Y:");
                    let response =
                        ui.add(egui::DragValue::new(&mut local_transform.scale.y).speed(0.01));
                    changed |= response.changed();
                    any_drag_started |= response.drag_started();
                    any_drag_released |= response.drag_stopped();

                    ui.label("Z:");
                    let response =
                        ui.add(egui::DragValue::new(&mut local_transform.scale.z).speed(0.01));
                    changed |= response.changed();
                    any_drag_started |= response.drag_started();
                    any_drag_released |= response.drag_stopped();
                }
                ui.checkbox(&mut self.uniform_scaling, "Uniform");
            });

            if any_drag_started {
                editor
                    .undo_history
                    .begin_transform_change(entity, initial_transform);
            }

            if any_drag_released {
                let final_transform = *local_transform;
                editor
                    .undo_history
                    .commit_transform_change(entity, final_transform);
            }

            if changed {
                let _ = local_transform;
                mark_local_transform_dirty(world, entity);
            }
        }
    }
}
