use super::components::NavMeshAgentState;
use crate::ecs::world::{
    BOUNDING_VOLUME, GLOBAL_TRANSFORM, LOCAL_TRANSFORM, LOCAL_TRANSFORM_DIRTY, MATERIAL_REF, NAME,
    NAVMESH_AGENT, RENDER_MESH, VISIBILITY, World,
};
use nalgebra_glm::Vec3;

pub fn spawn_navmesh_agent(world: &mut World, position: Vec3, speed: f32) -> freecs::Entity {
    let entity = world.spawn_entities(
        NAME | LOCAL_TRANSFORM
            | GLOBAL_TRANSFORM
            | LOCAL_TRANSFORM_DIRTY
            | RENDER_MESH
            | MATERIAL_REF
            | BOUNDING_VOLUME
            | VISIBILITY
            | NAVMESH_AGENT,
        1,
    )[0];

    if let Some(name) = world.get_name_mut(entity) {
        name.0 = "NavMesh Agent".to_string();
    }

    if let Some(transform) = world.get_local_transform_mut(entity) {
        transform.translation = position;
        transform.scale = nalgebra_glm::vec3(0.4, 0.8, 0.4);
    }

    if let Some(mesh) = world.get_render_mesh_mut(entity) {
        mesh.name = "Capsule".to_string();
    }

    if let Some(agent) = world.get_navmesh_agent_mut(entity) {
        agent.movement_speed = speed;
    }

    if let Some(bounding_volume) = world.get_bounding_volume_mut(entity) {
        *bounding_volume =
            crate::ecs::bounding_volume::components::BoundingVolume::from_mesh_type("Capsule");
    }

    if let Some(visibility) = world.get_visibility_mut(entity) {
        visibility.visible = true;
    }

    entity
}

pub fn set_agent_destination(world: &mut World, entity: freecs::Entity, destination: Vec3) {
    if let Some(agent) = world.get_navmesh_agent_mut(entity) {
        agent.target_position = Some(destination);
        agent.state = NavMeshAgentState::PathPending;
    }
}

pub fn stop_agent(world: &mut World, entity: freecs::Entity) {
    if let Some(agent) = world.get_navmesh_agent_mut(entity) {
        agent.clear_destination();
    }
}

pub fn set_agent_speed(world: &mut World, entity: freecs::Entity, speed: f32) {
    if let Some(agent) = world.get_navmesh_agent_mut(entity) {
        agent.movement_speed = speed;
    }
}

pub fn clear_navmesh(world: &mut World) {
    world.resources.navmesh.clear();
}

pub fn set_navmesh_debug_draw(world: &mut World, enabled: bool) {
    world.resources.navmesh.debug_draw = enabled;
}

pub fn get_agent_state(world: &World, entity: freecs::Entity) -> Option<NavMeshAgentState> {
    world.get_navmesh_agent(entity).map(|agent| agent.state)
}

pub fn get_agent_path_length(world: &World, entity: freecs::Entity) -> Option<usize> {
    world
        .get_navmesh_agent(entity)
        .map(|agent| agent.remaining_waypoints())
}
