//
// Created by sebastian on 29.07.26.
//

#ifndef COLORRACE_ENTITYREGISTRY_H
#define COLORRACE_ENTITYREGISTRY_H
#include <cstdint>
#include <memory>
#include <typeindex>
#include <unordered_map>

#include "ComponentPool.h"


namespace engine {
    class EntityRegistry {
    public:
        Entity createEntity() {
            return Entity{m_nextId++};
        }
        
        void destroyEntity(Entity entity) {
            for (auto& [type, pool] : m_pools) {
                pool->remove(entity);
            }
        }


        template<typename T>
        void addComponent(Entity entity, T component) {
            getPool<T>().insert(entity, std::move(component));
        }

        template<typename T>
        void removeComponent(Entity entity) {
            getPool<T>().remove(entity);
        }

        template<typename T>
        [[nodiscard]] bool hasComponent(Entity entity) {
            auto key = std::type_index(typeid(T));
            auto it = m_pools.find(key);
            if (it == m_pools.end()) return false;
            return static_cast<ComponentPool<T>&>(*it->second).has(entity);
        }

        template<typename T>
        T& getComponent(Entity entity) {
            return getPool<T>().get(entity);
        }

        template<typename T>
        ComponentPool<T>& getPool() {
            auto key = std::type_index(typeid(T));
            auto it = m_pools.find(key);
            if (it == m_pools.end()) {
                auto pool = std::make_unique<ComponentPool<T>>();
                auto* ptr = pool.get();
                m_pools.emplace(key, std::move(pool));
                return *ptr;
            }
            return static_cast<ComponentPool<T>&>(*it->second);
        }
    private:
        std::uint32_t m_nextId = 0;
        std::pmr::unordered_map<std::type_index, std::unique_ptr<IComponentPool>> m_pools;
    };
}

#endif //COLORRACE_ENTITYREGISTRY_H
