#include "BotTask.h"
#include "ISXMr.h"

#include <chrono>
#include <thread>

#include "UpdateUIPackageFile.h"
#include "lgui2.h"

std::weak_ptr<BotTask> BotTask::instance;

std::shared_ptr<BotTask> BotTask::Instance()
{
    auto existingInstance = instance.lock();
    if (!existingInstance)
    {
        existingInstance = std::shared_ptr<BotTask>(new BotTask());
        instance = existingInstance;
    }

    return existingInstance;
}

BotTask::BotTask()
{
    UpdateUIPackageFile(
        "bot_window.json",
        reinterpret_cast<const char *>(bot_window_json),
        bot_window_json_size);

    // UpdateUIPackageFile(
    //     "bot_cast_stack.json",
    //     reinterpret_cast<const char *>(bot_cast_stack_json),
    //     bot_cast_stack_json_len,
    //     bot_cast_stack_json_last_modified
    // );

    // pISInterface->RunScriptFromBuffer(
    //     ScriptName.c_str(),
    //     reinterpret_cast<const char *>(bot_controller_iss),
    //     bot_controller_iss_len
    // );

    this->onCloseButtonClickedEventId = pISInterface->RegisterEvent(OnClosedEventName.c_str());
    this->onToggleBotButtonClickedEventId = pISInterface->RegisterEvent(ToggleBotEventName.c_str());
    this->onToggleSettingsButtonClickedEventId = pISInterface->RegisterEvent(ToggleSettingsEventName.c_str());

    pISInterface->AttachEventTarget(this->onCloseButtonClickedEventId,
                                    &BotTask::OnCloseEventHandler);
    pISInterface->AttachEventTarget(this->onToggleBotButtonClickedEventId,
                                    &BotTask::OnToggleBotEventHandler);
    pISInterface->AttachEventTarget(this->onToggleSettingsButtonClickedEventId,
                                    &BotTask::OnToggleSettingsEventHandler);
}

void __cdecl BotTask::OnCloseEventHandler(int argc, char *argv[], PLSOBJECT plsObject)
{
    Instance()->Close();
}

void __cdecl BotTask::OnToggleBotEventHandler(int argc, char *argv[], PLSOBJECT plsObject)
{
    Instance()->ToggleBot();
}

void __cdecl BotTask::OnToggleSettingsEventHandler(int argc, char *argv[], PLSOBJECT plsObject)
{
    Instance()->ToggleSettings();
}

BotTask::~BotTask()
{
    pISInterface->DetachEventTarget(this->onCloseButtonClickedEventId, &BotTask::OnCloseEventHandler);
    pISInterface->UnregisterEvent(this->onCloseButtonClickedEventId);
    pISInterface->DetachEventTarget(this->onToggleBotButtonClickedEventId, &BotTask::OnToggleBotEventHandler);
    pISInterface->UnregisterEvent(this->onToggleBotButtonClickedEventId);
    pISInterface->DetachEventTarget(this->onToggleSettingsButtonClickedEventId, &BotTask::OnToggleSettingsEventHandler);
    pISInterface->UnregisterEvent(this->onToggleSettingsButtonClickedEventId);

    const std::string bufferScriptName = "Buffer:" + ScriptName;
    pISInterface->EndScript(bufferScriptName.c_str());
}

void BotTask::Execute()
{
    while (!this->stopRequested && !this->IsFinished())
    {
        // sleep for 100 ms
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void BotTask::Close()
{
    this->MarkFinished();
}

void BotTask::ToggleBot()
{
    isBotRunning = !isBotRunning;
    LSOBJECT obj;
    pISInterface->DataParse("BotController.StartButtonText", obj);
    auto stopStr = const_cast<char *>("Stop");
    char **argv = &stopStr;
    obj.Type->GetMethodEx(obj.GetObjectData(), const_cast<char *>("Set"), 1, argv);
    logw << "Type: " << obj.Type->GetName() << std::endl;
}

void BotTask::ToggleSettings()
{
}

TaskTypeEnum BotTask::TaskType() const
{
    return TaskTypeEnum::Bot;
}
