//
// Created by Dan Crosby on 4/18/22.
//

#include <iostream>

#include "MapInfoCalculator.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/settings/GameSettings.hpp"
#include "src/main/cpp/net/eagle0/shardok/util/BattalionTypeRegistrar.hpp"
#include "src/main/cpp/net/eagle0/shardok/util/MapLoader.hpp"

using namespace shardok;
using std::endl;

auto main(const int argc, char** argv) -> int {
    FilesystemUtils::SetExecPath(argv[0]);

    std::ostream* outputStreamPtr = &std::cout;
    if (argc > 1) {
        const string outputPath = argv[1];
        outputStreamPtr = new std::ofstream(outputPath);
    }
    std::ostream& outputStream = *outputStreamPtr;

    const auto gameSettings = std::make_shared<GameSettings>();
    auto setter = gameSettings->GetSetter();
    BattalionTypeRegistrar::RegisterBattalionTypes(setter);
    const BattalionTypeSPtr& battalionType = gameSettings->GetGetter().GetBattalionType(
            net::eagle0::shardok::storage::fb::BattalionTypeId_LIGHT_INFANTRY);

    vector<OneMapInfo> mapInfos{};
    for (const string& mapName : GetMapNames()) {
        std::shared_ptr<ActionPointDistancesCache> apdCache =
                std::make_shared<ActionPointDistancesCache>();

        mapInfos.push_back(CalculateMap(mapName, apdCache, battalionType));
    }

    outputStream << "[";
    bool firstMap = true;
    for (const OneMapInfo& mapInfo : mapInfos) {
        if (firstMap) {
            outputStream << endl;
            firstMap = false;
        } else {
            outputStream << "," << endl;
        }
        outputStream << "  {" << endl;
        outputStream << R"(    "name": ")" << mapInfo.name << "\"," << endl;

        outputStream << "    \"castleCount\": " << mapInfo.castleCount << "," << endl;
        outputStream << "    \"positions\": {";

        bool firstPosition = true;
        for (const auto& kv : mapInfo.positionsRequiringCrossing) {
            if (firstPosition) {
                outputStream << endl;
                firstPosition = false;
            } else {
                outputStream << "," << endl;
            }

            outputStream << "      \"" << kv.first << "\": " << kv.second;
        }
        outputStream << endl << "    }" << endl << "  }";
    }
    outputStream << endl << "]" << endl;
}
