use anyhow::Result;
use glam::Vec3;

use crate::loaders::empty::Empties;
use crate::loaders::lights::{LightData, Lights};
use crate::loaders::mesh::{InstanceData, Mesh};
use crate::render;

pub const CAMERA_SPAWN_OFFSET: Vec3 = Vec3::new(15.0, 15.0, 15.0);

pub struct Space
{
    pub mesh_data: Vec<(Mesh, Vec<InstanceData>)>,
    pub spotlights: Vec<LightData>,
    pub player_spawn: Vec3,
    pub test_char_spawn: Vec3,
}

impl Space
{
    pub fn load_space(gltf_path: &str) -> Result<Space>
    {
        let mesh_data =
            render::with_device(|device| Mesh::load_gltf_with_instances(device, gltf_path))?;

        let lights = Lights::load_lights(gltf_path)
            .map_err(|e| anyhow::anyhow!("Failed to load lights: {}", e))?;

        let spotlights = lights.into_spotlights();

        let player_spawn = Self::get_spawn(gltf_path, "PlayerSpawn")?;
        let test_char_spawn = Self::get_spawn(gltf_path, "TestCharSpawn")?;

        Ok(Space {
            mesh_data,
            spotlights,
            player_spawn,
            test_char_spawn,
        })
    }

    fn get_spawn(gltf_path: &str, name: &str) -> Result<Vec3>
    {
        let empty = Empties::get_empty_by_name(gltf_path, name)?;

        if let Some(empty_node) = empty
        {
            let (_scale, _rotation, translation) =
                empty_node.transform.to_scale_rotation_translation();
            Ok(translation)
        }
        else
        {
            println!("Warning: {} empty not found, using default position", name);
            Ok(Vec3::new(0.0, 5.0, 0.0))
        }
    }

    pub fn camera_spawn_position(&self) -> Vec3
    {
        self.player_spawn + CAMERA_SPAWN_OFFSET
    }

    pub fn terrain_mesh(&self) -> Option<&Mesh>
    {
        self.mesh_data.first().map(|(mesh, _)| mesh)
    }

    pub fn tree_instances(&self) -> Option<(&Mesh, &Vec<InstanceData>)>
    {
        self.mesh_data
            .iter()
            .find(|(_, instances)| !instances.is_empty())
            .map(|(mesh, instances)| (mesh, instances))
    }
}
