//! Stable, typed handles for GPU resources.
//! All handles are small (u32), Copy, and Hash-safe for use as map keys.

/// Mesh resource handle with generation counter for dangling reference detection.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MeshHandle(pub u32, pub u32);

/// Texture resource handle with generation counter for dangling reference detection.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TextureHandle(pub u32, pub u32);

/// Material resource handle with generation counter for dangling reference detection.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MaterialHandle(pub u32, pub u32);

/// Font resource handle.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FontHandle(pub u32);

/// Sound resource handle (defined here for cross-crate use).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SoundHandle(pub u32);

/// Scene handle (loaded scene reference).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SceneHandle(pub u32);

/// Content pack handle.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PackHandle(pub u32);

/// Particle emitter handle.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EmitterHandle(pub u32);

/// Camera handle.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct CameraHandle(pub u32);

/// Dreamlet (data-driven game object) handle.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DreamletHandle(pub u32);

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::HashMap;

    #[test]
    fn handles_are_copy() {
        let h = MeshHandle(42, 0);
        let h2 = h; // Copy
        assert_eq!(h, h2);
    }

    #[test]
    fn handles_as_map_keys() {
        let mut map = HashMap::new();
        map.insert(TextureHandle(1, 0), "albedo");
        map.insert(TextureHandle(2, 0), "normal");
        assert_eq!(map.get(&TextureHandle(1, 0)), Some(&"albedo"));
    }

    #[test]
    fn handle_types_distinct() {
        // Ensure different handle types don't accidentally compare equal.
        // (They can't -- different types. This just confirms the API.)
        let _m = MeshHandle(1, 0);
        let _t = TextureHandle(1, 0);
        // These are different types, so no equality comparison is possible.
    }

    #[test]
    fn generation_distinguishes_handles() {
        let h1 = MeshHandle(0, 0);
        let h2 = MeshHandle(0, 1);
        assert_ne!(h1, h2);
    }
}
