#include <chrono>
#include <fstream>
#include <future>
#include <thread>
#include <json_struct/json_struct.h>

#include "ISXMr.h"
#include "ExportAbilitiesTask.h"

#include <filesystem>

#include "Logger.h"
#include "isxeq2/ExtensionTLOs.h"

using namespace std;

AbilityInfo GetAbilityInfo(const int idx)
{
    const auto ability = ExtensionTLOs::Me().Ability(idx);
    while (!ability.IsAbilityInfoAvailable())
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    return ability.GetAbilityInfo();
}

void ExportAbilitiesTask::Execute()
{
    try
    {
        log << "Exporting abilities" << endl;
        const auto numAbilities = ExtensionTLOs::Me().NumAbilities();
        auto abilityList = map<string, vector<ExportedAbility>>{};
        for (int i = 1; i <= numAbilities && !IsStopRequested(); ++i)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(200));
            while (!ExtensionTLOs::Me().Ability(i).IsAbilityInfoAvailable() && !IsStopRequested())
            {
                std::this_thread::sleep_for(std::chrono::milliseconds(200));
            }

            if (IsStopRequested())
            {
                log << "Exporting abilities cancelled" << endl;
                return;
            }
            const auto exportedAbility = ExtensionTLOs::Me().Ability(i).ToExportedAbility();
            log << "Exporting " << exportedAbility.Name << " (" << i << "/" << numAbilities << ")" << endl;

            const auto abilityLineName = StripTrailingRomanNumerals(exportedAbility.Name);
            abilityList[abilityLineName].push_back(exportedAbility);
        }

        constexpr size_t innerspacePathBufferLength = 255;
        char innerspacePathBuffer[innerspacePathBufferLength];
        const filesystem::path innerspacePath = pISInterface->GetInnerSpacePath(
            innerspacePathBuffer, innerspacePathBufferLength);
        ostringstream filename;
        filename << ExtensionTLOs::Me().Name() << "_" << ExtensionTLOs::Me().SubClass() << "_" << ExtensionTLOs::EQ2().ServerName()
                 << ".json";
        filesystem::path fullPath = innerspacePath /
                                    R"(scripts\mr\bot\ability_exports)" /
                                    filename.str();

        if (fullPath.has_parent_path() && !exists(fullPath.parent_path()))
        {
            create_directories(fullPath.parent_path());
        }

        if (std::ofstream file(fullPath); file)
        {
            std::string pretty_json = JS::serializeStruct(abilityList);
            file << pretty_json << endl;
        }
        else
        {
            loge << "Unknown error writing export to disk" << endl;
        }
    }
    catch (const std::exception &e)
    {
        loge << "Error exporting abilities: " << e.what() << endl;
    }
    catch (...)
    {
        loge << "Unknown error exporting abilities" << endl;
    }

    log << "Exporting abilities finished" << endl;
}
