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

#include "MapInfoCalculator.hpp"

#include <cstddef>
#include <cstdlib>
#include <iostream>

#include "src/main/cpp/net/eagle0/shardok/ai/AIWaterCrossingCalculator.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/fb_helpers/HexMapHelpers.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/util/HexMapUtils.hpp"
#include "src/main/cpp/net/eagle0/shardok/util/MapLoader.hpp"

auto LoadMapFb(const std::string& mapName) -> shardok::Wrapper<shardok::HexMap> {
    const HexMapProto mapProto = LoadMap(mapName);

    flatbuffers::FlatBufferBuilder fbb{};
    const auto hexMapOffset = shardok::fb::ConvertHexMapProto(fbb, mapProto);
    fbb.Finish(hexMapOffset);
    return shardok::Wrapper<shardok::HexMap>(fbb);
}

auto CalculateMap(
        const std::string& mapName,
        const std::shared_ptr<shardok::ActionPointDistancesCache>& apdCache,
        const shardok::BattalionTypeSPtr& battalionType) -> OneMapInfo {
    auto hexMap = LoadMapFb(mapName);

    const auto mapId = shardok::ActionPointDistancesCache::GetMapId(hexMap);

    const shardok::CoordsSet criticalTileLocations = shardok::GetCriticalTileLocations(hexMap);

    OneMapInfo info{
            .castleCount = criticalTileLocations.size(),
            .name = mapName,
            .positionsRequiringCrossing = {}};

    for (std::size_t i = 0; i < hexMap->attacker_starting_positions()->size(); ++i) {
        const auto* positionList = hexMap->attacker_starting_positions()->Get(i);
        const auto* positions = positionList->positions();
        if (positions->empty()) continue;
        if (positions->size() != 10) {
            std::cerr << "Should have 10 starting positions!" << '\n';
            std::abort();
        }

        int positionsRequiringCrossing = 0;
        for (const auto* startingPosition : *positions) {
            for (const shardok::Coords& castlePosition : criticalTileLocations) {
                if (!shardok::CanReach(
                            *startingPosition,
                            castlePosition,
                            hexMap,
                            mapId,
                            apdCache,
                            battalionType)) {
                    ++positionsRequiringCrossing;
                    break;
                }
            }
        }
        info.positionsRequiringCrossing[static_cast<int>(i)] = positionsRequiringCrossing;
    }

    return info;
}
