#![allow(dead_code)]

use crate::foundation::core::entity::{EntityVersion, EntityRID, Entity};

pub struct EntityRepository {
    version_of_entities: Box<[EntityVersion]>,
    max_version_of_entities: Box<[EntityVersion]>,
    entities_capacity: usize,
    lack_count: usize
}

fn alloc_u32(n: usize) -> Box<[u32]> {
    vec![0u32; n].into_boxed_slice()
}

impl EntityRepository {
    pub fn new(entity_count_to_generate: usize) -> EntityRepository {
        EntityRepository {
            version_of_entities: alloc_u32(entity_count_to_generate),
            max_version_of_entities: alloc_u32(entity_count_to_generate),
            entities_capacity: 0,
            lack_count: 0
        }
    }

    pub fn create_entity(&mut self) -> EntityRID {
        if self.lack_count > 0 {
            for i in 0..self.entity_capacity() {
                if self.version_of_entities[i] == 0 {
                    self.max_version_of_entities[i] += 1;
                    self.version_of_entities[i] = self.max_version_of_entities[i];
                    self.lack_count -= 1;
                    return i as EntityRID;
                }
            }
        }
        self.version_of_entities[self.entities_capacity] = 1u32;
        self.max_version_of_entities[self.entities_capacity] = 1u32;
        let entity_rid = self.entities_capacity;
        self.entities_capacity += 1;
        entity_rid as EntityRID
    }

    pub fn delete_entity(&mut self, entity_rid: EntityRID) {
        self.version_of_entities[entity_rid as usize] = 0;
        self.lack_count += 1;
    }

    pub fn entity_capacity(&self) -> usize {
        self.entities_capacity
    }

    pub fn entity_count(&self) -> usize {
        self.entities_capacity - self.lack_count
    }

    pub fn entity_version(&self, entity_rid: EntityRID) -> EntityVersion {
        self.version_of_entities[entity_rid as usize]
    }

    pub fn entity_object(&self, entity_rid: EntityRID) -> Entity {
        Entity::new(entity_rid, self.version_of_entities[entity_rid as usize])
    }
}

