/******************************************************************************
*	File		-	world.h
*	Author		-	Joey Pollack
*	Date		-	2022/06/28 (y/m/d)
*	Mod Date	-	2022/06/28 (y/m/d)
*	Description	-	Editor asset for a World object
******************************************************************************/

#include "world.h"
#include <LunariumConfig.h>
#include <editor/editor.h>
#include <world/world.h>
#include <dearimgui/imgui.h>
#include <gui/imgui_ext.h>

#include <filesystem>
#include <fstream>

namespace lunarium { namespace editor 
{
    World::World(std::filesystem::path name)
        : EditorAsset(AssetType::EATYPE_WORLD), mpWorld(new lunarium::World(name.stem().string()))
    {
        mLocation = name.string() + ".wld";
    }

    World::~World()
    {
        delete mpWorld;
    }

    lunarium::World* World::GetWorld()
    {
        return mpWorld;
    }

    
    void World::UnloadWorld()
    {
        delete mpWorld;
        mpWorld = nullptr;
    }

    OpRes World::LoadWorld()
    {
        return LoadRawFile();
    }

    OpRes World::LoadRawFile()
    {
        return OpRes::OK();
    }

    OpRes World::Deserialize(nlohmann::ordered_json& node)
    {
        #if !BUILD_NO_EDITOR // Only does this when this is an editor build

        std::filesystem::path file_path = mAssetDir / mLocation;
        std::ifstream ifs = std::ifstream(file_path.string().c_str());
        if (!ifs.is_open())
        {
            return OpRes::Fail("Could not open contents file: %s", file_path.string().c_str());
        }

        nlohmann::ordered_json world_file;
        ifs >> world_file;
        ifs.close();

        if (mpWorld)
        {
            mpWorld->Deserialize(world_file).LogIfFailed(Editor::LogCat);
        }

        #endif
        return OpRes::OK();
    }

    OpRes World::Serialize(nlohmann::ordered_json& node)
    {
        #if !BUILD_NO_EDITOR // Only does this when this is an editor build

        nlohmann::ordered_json world_file;
        
        if (mpWorld)
        {
            mpWorld->Serialize(world_file).LogIfFailed(Editor::LogCat);
        }

        std::filesystem::path file_path = mAssetDir / mLocation;
        std::ofstream ofs = std::ofstream(file_path.string().c_str(), std::ios_base::trunc);
        if (!ofs.is_open())
        {
            return OpRes::Fail("Could not save file: %s", file_path.string().c_str());
        }

        ofs << std::setw(4) << world_file;
        ofs.close();


        #endif
        return OpRes::OK();
    }

    
    bool World::IsValidNode(nlohmann::ordered_json& node)
    {
        
        return true;
    }

    nlohmann::ordered_json World::AsJSON()
    {
        #if !BUILD_NO_EDITOR // Only does this when this is an editor build
        nlohmann::ordered_json node;

        Serialize(node).LogIfFailed(Editor::LogCat);

        return node;
        #endif

        return nlohmann::ordered_json();
    }
    
    bool World::DrawProperties()
    {
        std::string name = mpWorld->GetName();
        char buffer[256];
        strcpy(buffer, name.c_str());
        ImGui::Text("World Name: ");
        ImGui::SameLine();
        bool result0 = ImGui::InputText("##World Name", buffer, 256);
        if (result0) mpWorld->SetName(buffer);

        // Show gravity and Physics scale value
        glm::vec2 gravity = mpWorld->GetGravity();
        bool result1 = ImGuiExt::Vec2Control("World Gravity", gravity);
        if (result1) mpWorld->SetGravity(gravity);

        float scale = mpWorld->GetPhysicsScaleFactor();
        ImGui::Text("World Physics Scale Factor:");
        ImGui::SameLine();
        bool result2 = ImGui::DragFloat("##Scale Factor", &scale);
        if (result2) mpWorld->SetPhysicsScaleFactor(scale);

        return (result0 || result1 || result2);
    }

}}