use nightshade::prelude::*;

pub struct WorldTreeUi;

impl WorldTreeUi {
    pub fn ui_with_pointers(
        world: *mut World,
        selected_entity: *mut Option<Entity>,
        ui: &mut egui::Ui,
    ) {
        let world = unsafe { &mut *world };
        let selected_entity = unsafe { &mut *selected_entity };
        Self::ui_internal(world, selected_entity, ui);
    }

    fn ui_internal(world: &mut World, selected_entity: &mut Option<Entity>, ui: &mut egui::Ui) {
        ui.horizontal(|ui| {
            if ui.button("New Entity").clicked() {
                EntityBuilder::new()
                    .with_local_transform(LocalTransform::default())
                    .with_global_transform(GlobalTransform::default())
                    .spawn(world, 1);
            }
        });
        for entity in query_root_nodes(world) {
            Self::entity_tree_ui_internal(world, selected_entity, ui, entity);
        }
    }

    fn entity_tree_ui_internal(
        world: &mut World,
        selected_entity: &mut Option<Entity>,
        ui: &mut egui::Ui,
        entity: Entity,
    ) {
        if Self::is_gizmo_entity(world, entity) {
            return;
        }

        let id = ui.make_persistent_id(entity.id);
        egui::collapsing_header::CollapsingState::load_with_default_open(ui.ctx(), id, true)
            .show_header(ui, |ui| {
                Self::entity_tree_header_ui_internal(world, selected_entity, entity, ui);
            })
            .body(|ui| {
                for child in query_children(world, entity) {
                    Self::entity_tree_ui_internal(world, selected_entity, ui, child);
                }
            });
    }

    fn entity_tree_header_ui_internal(
        world: &mut World,
        selected_entity: &mut Option<Entity>,
        entity: Entity,
        ui: &mut egui::Ui,
    ) {
        let selected = *selected_entity == Some(entity);
        let name = if let Some(Name(name)) = world.get_name(entity) {
            name.to_string()
        } else {
            format!("Entity {}", entity.id)
        };

        ui.horizontal(|ui| {
            let prefix = "🔵";
            let response = ui.selectable_label(selected, format!("{} {}", prefix, name));
            if response.clicked() {
                *selected_entity = Some(entity);
            }

            response.context_menu(|ui| {
                if ui.button("Add Entity").clicked() {
                    Self::add_entity_internal(world, selected_entity, entity);
                    ui.close();
                }

                if ui.button("Remove").clicked() {
                    world.queue_command(WorldCommand::DespawnRecursive { entity });
                    *selected_entity = None;
                    ui.close();
                }
            });
        });
    }

    fn add_entity_internal(
        world: &mut World,
        selected_entity: &mut Option<Entity>,
        parent_entity: Entity,
    ) {
        let entities = EntityBuilder::new()
            .with_name(Name(String::new()))
            .with_local_transform(LocalTransform::default())
            .with_global_transform(GlobalTransform::default())
            .with_parent(Parent(Some(parent_entity)))
            .spawn(world, 1);
        let new_entity = entities[0];

        if let Some(name) = world.get_name_mut(new_entity) {
            *name = Name(format!("Entity {}", new_entity.id));
        }

        *selected_entity = Some(new_entity);
    }

    fn is_gizmo_entity(world: &World, entity: Entity) -> bool {
        if let Some(Name(name)) = world.get_name(entity) {
            name.ends_with("Gizmo")
        } else {
            false
        }
    }
}
