//! Latticeon ECS: Archetype-based ECS with SoA-in-block storage and multi-threading support.

pub mod archetype;
pub mod commands;
pub mod component;
pub mod entity;
pub mod processor;
pub mod query;
pub mod schedule;
pub mod storage;
pub mod universe;

pub use archetype::{Archetype, ArchetypeBuilder, ArchetypeId, ComponentBundle};
pub use commands::Commands;
pub use component::{Component, ComponentId, ComponentIdRegistry, ComponentMeta};
pub use entity::{Entity, EntityAllocator};
pub use latticeon_macros::Component;
pub use processor::{AllowRead, AllowWrite, Processor, ProcessorContext};
pub use query::{QueryFetch, QueryFetchMut, QueryFilter, QueryIter, QueryIterMut};
pub use schedule::{ProcessorGroup, Schedule, Stage, StageNode};
pub use storage::DEFAULT_BLOCK_SIZE;
pub use universe::{ArchetypeHandle, EntityBuilder, Universe};

/// Optional type alias for users who prefer the name "World".
pub type World = Universe;

pub mod prelude {
    pub use crate::ecs::archetype::{ArchetypeBuilder, ComponentBundle};
    pub use crate::ecs::commands::Commands;
    pub use crate::ecs::entity::Entity;
    pub use crate::ecs::processor::{AllowRead, AllowWrite, Processor, ProcessorContext};
    pub use crate::ecs::query::{QueryFetch, QueryFetchMut, QueryFilter};
    pub use crate::ecs::schedule::{ProcessorGroup, Schedule, Stage, StageNode};
    pub use crate::ecs::universe::{ArchetypeHandle, EntityBuilder, Universe};
    pub use crate::ecs::World;
    pub use crate::ecs::Component;
    pub use latticeon_macros::Processor;
}

#[cfg(test)]
mod tests {
    use crate::ecs::component::Component;
    use crate::ecs::prelude::*;

    #[derive(Debug, Clone, PartialEq)]
    struct Position(i32, i32);
    impl Component for Position {}

    #[derive(Debug, Clone, PartialEq)]
    struct Velocity(i32, i32);
    impl Component for Velocity {}

    #[test]
    fn lib_spawn_query() {
        let mut u = Universe::new();
        let e = u.spawn((Position(1, 2), Velocity(3, 4)));
        assert_eq!(u.get::<Position>(e), Some(&Position(1, 2)));
        let count = u.query::<(&Position, &Velocity)>().count();
        assert_eq!(count, 1);
    }
}
