//
// Created by Dan Crosby on 12/29/21.
//

#ifndef EAGLE0_AIWATERCROSSINGCALCULATOR_HPP
#define EAGLE0_AIWATERCROSSINGCALCULATOR_HPP

#include "src/main/cpp/net/eagle0/shardok/library/action_point_distances/ActionPointDistancesCache.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/map/CoordsSet.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/settings/GameSettings.hpp"
#include "src/main/flatbuffer/net/eagle0/shardok/storage/game_state.hpp"

namespace shardok {

using GameState = net::eagle0::shardok::storage::fb::GameState;

static inline void AssertValid(const Coords& c, const HexMap* hexMap) {
    const bool valid =
            (c.row() >= 0 && c.column() >= 0 && c.row() < hexMap->row_count() &&
             c.column() < hexMap->column_count());

    if (!valid) {
        std::stringstream str;
        str << "Invalid coords " << (int)c.row() << ", " << (int)c.column();

        throw ShardokInternalErrorException(str.str());
    }
}

// Units that need a water crossing to reach at least one of the destinations
auto UnitIdsRequiringWaterCrossing(
        const GameState* gameState,
        PlayerId pid,
        const CoordsSet& destinations,
        const APDCache& apdCache,
        const SettingsGetter& settings) -> vector<UnitId>;

// Units belonging to the player that are capable of creating water crossings
auto UnitIdsToCreateWaterCrossing(
        const GameState* gameState,
        PlayerId pid,
        const APDCache& apdCache,
        const SettingsGetter& settings) -> vector<UnitId>;

// Whether a unit of the given type can reach destination from origin, given the current state
// of the map
auto CanReach(
        const Coords& origin,
        const Coords& destination,
        const HexMap* hexMap,
        const MapId& mapId,
        const APDCache& apdCache,
        const BattalionTypeSPtr& battalionType) -> bool;

// Returns the *non*-water tiles from which you could bridge/freeze water to allow a unit to cross
// from origin to destination
auto CrossingStartLocations(const HexMap* hexMap, const CoordsSet& waterCrossingTiles) -> CoordsSet;

// Returns the water tiles that, if they were bridged/frozen, would allow a unit to cross from
// origin to destination
auto WaterCrossingTiles(
        const Coords& origin,
        const Coords& destination,
        const HexMap* hexMap,
        const APDCache& apdCache,
        const BattalionTypeSPtr& battalionType) -> CoordsSet;

// Returns the set of tiles that the attacker should try to approach in order to bridge/freeze
auto IntendedCrossingStarts(
        const GameState* gameState,
        const vector<UnitId>& unitIdsCreatingCrossing,
        const CoordsSet& tilesToStartCrossingFrom,
        const MapId& mapId,
        const APDCache& apdCache,
        const SettingsGetter& settings) -> CoordsSet;

}  // namespace shardok

#endif  // EAGLE0_AIWATERCROSSINGCALCULATOR_HPP
