/******************************************************************************
*	File		-	world.cpp
*	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.
******************************************************************************/

#include "world.h"
#include <object/object.h>
#include <assets/types/script.h>
#include <assets/types/image.h>
#include <graphics/graphics.h>
#include <graphics/camera.h>

namespace lunarium { namespace game
{
    World::World(Camera* pCam, Sizei region_size, Sizei world_size)
        : mpCamera(pCam), mRegionSize(region_size), mpWorldScript(nullptr), mRegions(region_size), mWorldSize(world_size)
    {
        mActiveRegion = { 0, 0 };
        mRegions.SetAll(nullptr);
    }

    void World::OnLoad()
    {
        // TODO: Call OnLoad in the world script and on each region script
    }
    
    void World::OnUnload()
    {
        // TODO: Call OnUnLoad in the world script and on each region script
    }
    
    void World::Update(float dt)
    {
        // TODO: Call Update in the world script and on each region script
    }
    
    void World::Render(Graphics* pGraphics) const
    {
        // TODO: Call Render in the world script and on each region
    }
    
    void World::RenderToTexture(Graphics* pGraphics, Image* pTexture) const
    {

    }
    
    // void World::AddGameObject(GameObject* pObj)
    // {

    // }
    
    // bool World::RemoveGameObject(GameObject* pObj)
    // {

    // }
    

    OpRes World::SetRegion(Region* region, Vec2i at)
    {
        if (*mRegions[at] != nullptr)
        {
            return OpRes::Fail("World::SetRegion failed because a region already exists at (%n, %n)", at.X, at.Y);
        }

        // Validate the layers - each image needs to match the region size
        for (int i = 0; i < region->mLayers.size(); i++)
        {
            if (region->mLayers[i]->GetWidth() != mRegionSize.Width 
                || region->mLayers[i]->GetHeight() != mRegionSize.Height)
                {
                    return OpRes::Fail("World::SetRegion failed because the region contains layers that do not match the region size");
                }
        }

        *mRegions[at] = region;
        return OpRes::OK();
    }

    World::Region* World::GetRegion(Vec2i at)
    {
        return *mRegions[at];
    }
    
    bool World::RemoveRegion(Vec2i at)
    {
        if (*mRegions[at] == nullptr)
        {
            return false;
        }

        *mRegions[at] = nullptr;
        return true;
    }

    void World::SetWorldScript(Script* pScript)
    {
        mpWorldScript = pScript;
    }
    
    Script* World::GetWorldScript()
    {
        return mpWorldScript;
    }

}}