/******************************************************************************
*	File		-	world.h
*	Author		-	Joey Pollack
*	Date		-	2022/01/12 (y/m/d)
*	Mod Date	-	2022/01/20 (y/m/d)
*	Description	-	Manages a game "world". A world is made up of regions which
*                   are subdivisions of the world. Each region contains: a set 
*                   of images for the maps layers, a list of objects that spawn
*                   in this region and static collision data.
******************************************************************************/

#ifndef LUNARIUM_WORLD_H_
#define LUNARIUM_WORLD_H_

#include <core/common_defs.h>
#include <core/types.h>
#include <assets/serializing/json_serializable.h>
#include <utils/op_res.h>
#include <entt/entt.hpp>

#include <vector>
#include <map>

namespace lunarium
{
    class IGraphics;
    class Image;
    class Script;
    class OrthographicCamera;
    //class GameObject;
    class Entity;
}

namespace lunarium 
{
    struct EntityIterator
    {
        Entity* mEntity;
        int Index;
    };

    class World : public JSONSerializable
    {
    public:
        struct Region
        {
            bool IsActive;
            lunarium::Script* RegionScript;
            Vec2i Coords;
            std::vector<Entity*> Entities;
            std::vector<lunarium::Image*> mLayers;
        };

    public:     // INTERFACE

        //World(Camera* pCam, Sizei region_size, Sizei world_size);
        World(std::string name);

        void OnLoad();
        void OnUnload();
        void Update(float dt);
        void Render(lunarium::IGraphics* pGraphics) const;

        void SetActiveCamera(OrthographicCamera* pCam);

        entt::registry* GetEntityRegistry();
        LUUID CreateEntity();
        Entity* GetEntity(LUUID id);
        unsigned int GetNumEntities() const;
        std::vector<Entity*>::iterator EntitiesBegin();
        bool EntitiesIsEnd(std::vector<Entity*>::iterator& iter);

        // Serializing
        [[nodiscard]] virtual OpRes Serialize(nlohmann::ordered_json& node);
        [[nodiscard]] virtual OpRes Deserialize(nlohmann::ordered_json& node);
        [[nodiscord]] virtual bool IsValidNode(nlohmann::ordered_json& node);
        [[nodiscard]] virtual nlohmann::ordered_json AsJSON();


    private:
        LUUID mUUID;
        std::string mName;
        entt::registry mECSRegistry;
        std::vector<Entity*> mEntities;

        OrthographicCamera* mpActiveCamera;

        // TODO: Move these into a TileMap class?
        // This would allow worlds to support non-tile based levels/worlds
        Sizei mRegionSize;      // in tiles
        Sizei mWorldSize;       // num regions ex. 10x10
        Vec2i mActiveRegion;


        // TEST STUFF
        std::map<LUUID, Entity*> mEntitiesByUUID;
        

    };
}

#endif  // LUNARIUM_WORLD_H_