/******************************************************************************
*	File		-	entity.h
*	Author		-	Joey Pollack
*	Date		-	2022/05/23 (y/m/d)
*	Mod Date	-	2022/05/23 (y/m/d)
*	Description	-	Provides functionality to work with world entities
******************************************************************************/

#ifndef LUNARIUM_ENTITY_H_
#define LUNARIUM_ENTITY_H_

#include <utils/uuid.h>
#include <utils/logger.h>
#include <entt/entt.hpp>

namespace lunarium
{
    class Entity
    {
    public:
        // TODO: Maybe change this to take the World instead of the registry
        Entity(entt::registry* r);
        Entity(entt::registry* r, LUUID uuid);

        // These component methods are based on methods from the Hazel engine, written by Cherno
        // https://github.com/TheCherno/Hazel/blob/dev/Hazel/src/Hazel/Scene/Entity.h
        template<typename T, typename... Args>
		T& AddComponent(Args&&... args)
		{
			if (HasComponent<T>())
            {
                Log::Error(LogCategory::GAME_SYSTEM, "Entity already has component!");
                return GetComponent<T>();
            }
			T& component = mpRegistry->emplace<T>(mHandle, std::forward<Args>(args)...);
			//m_Scene->OnComponentAdded<T>(*this, component);
			return component;
		}

        template<typename T>
		T& GetComponent()
		{
			if (!HasComponent<T>())
            {
                Log::Error(LogCategory::GAME_SYSTEM, "Entity does not have component!");
            }
			return mpRegistry->get<T>(mHandle);
		}

		template<typename T>
		bool HasComponent()
		{
			return mpRegistry->all_of<T>(mHandle);
		}

		template<typename T>
		void RemoveComponent()
		{
			if (!HasComponent<T>())
            {
                Log::Error(LogCategory::GAME_SYSTEM, "Entity does not have component!");
            }
			m_Scene->m_Registry.remove<T>(mHandle);
		}

    private:
        LUUID mUUID;
        entt::entity mHandle;
        entt::registry* mpRegistry;
    };
}

#endif  // LUNARIUM_ENTITY_H_