/******************************************************************************
*	File		-	script_manager.cpp
*	Author		-	Joey Pollack
*	Date		-	2021/08/30 (y/m/d)
*	Mod Date	-	2021/09/02 (y/m/d)
*	Description	-	Manage the main LUA state, Run given scripts and check for
*                   errors. Report errors in the debug log. Also keep a 
*                   history of errors that can be queried.
******************************************************************************/

#include "script_manager.h"
#include <utils/logger.h>
#include <sstream>

namespace lunarium
{
    ScriptManager* ScriptManager::mpInstance = nullptr;
    ScriptManager& ScriptManager::GetInstance()
    {
        if (mpInstance == nullptr)
        {
            mpInstance = new ScriptManager;
        }

        return *mpInstance;
    }

    void ScriptManager::FreeInstance()
    {
        delete mpInstance;
        mpInstance = nullptr;
    }

    OpRes ScriptManager::Initialize()
    {
        mCat = Logger::RegisterCategory("LUA");

        mState.open_libraries(sol::lib::base, sol::lib::package);
        // mState.script("print('test puppy says: bark bark bark!')");

        return OpRes::OK();
    }
    
    OpRes ScriptManager::RunScript(const char* code)
    {
        if (!mpInstance)
        {
            return OpRes::Fail("ScriptManager::RunScript failed because the instance is null!");
        }

        // TODO: Use the state to run the script and check for errors
        auto result = mpInstance->mState.script(code, [](lua_State*, sol::protected_function_result pfr) {
            return pfr;
        });

        if (!result.valid())
        {
            sol::error err = result;
            Logger::Warn(mpInstance->mCat, "LUA script has errors");
            std::ostringstream oss;
            oss << "LUA code has error. CODE:\n" << code << "\nEND CODE -- ERROR: " << err.what();
            return OpRes::Fail(oss.str().c_str());
        }

        return OpRes::OK();
    }
}