//
// Created by Dan Crosby on 3/10/21.
//

#include "RepairCommandFactory.hpp"

#include "src/main/cpp/net/eagle0/shardok/library/commands/RepairCommand.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/util/HexMapUtils.hpp"

namespace shardok {

[[nodiscard]] auto GetRepairOdds(
        const SettingsGetter &settings,
        double strength,
        double agility,
        double intelligence,
        bool hasForestAccess) -> PercentileRollOdds;

void RepairCommandFactory::AddAvailableRepairCommands(
        CommandList &commands,
        const Unit *unit,
        const ActionPoints remainingActionPoints,
        const Coords &position,
        const HexMap *hexMap,
        const Units *units,
        const vector<PlayerId> &allyPids) const {
    const PlayerId playerId = unit->player_id();
    if (!unit->has_attached_hero()) return;
    const auto &hero = unit->attached_hero();
    const auto *currentTerrain = GetTerrain(hexMap, position);

    // Can't repair from water
    if (hero.profession_info().profession() ==
                net::eagle0::shardok::storage::fb::Profession_ENGINEER &&
        !IsWater(currentTerrain->type())) {
        const ActionCost cost =
                settings.ActionCostFor(settings.Backing().repair_action_point_cost());

        if (cost.IsPossible(remainingActionPoints)) {
            CoordsSet coordsToCheck = HexMapUtils::GetAdjacentCoords(hexMap, position);
            coordsToCheck.Add(position);

            for (const Coords &coords : coordsToCheck) {
                if (KnownEnemyOccupant(playerId, units, allyPids, coords)) continue;
                const auto *terrain = GetTerrain(hexMap, coords);
                if ((terrain->modifier().bridge().present() &&
                     terrain->modifier().bridge().integrity() < 100.0) ||
                    (terrain->modifier().castle().present() &&
                     terrain->modifier().castle().integrity() < 100.0)) {
                    commands.push_back(std::make_shared<RepairCommand>(
                            settings.ActionCostFor(settings.Backing().repair_action_point_cost()),
                            unit->player_id(),
                            unit->unit_id(),
                            coords,
                            settings.Backing().repair_agility_xp(),
                            settings.Backing().repair_strength_xp(),
                            settings.Backing().minimum_knowledge_for_profession(),
                            settings.Backing().repair_buf()));
                }
            }
        }
    }
}
void RepairCommandFactory::AddAvailableCommands(CommandList &commands, const CommandParams &params)
        const {
    AddAvailableRepairCommands(
            commands,
            params.unit,
            params.remainingActionPoints,
            params.position,
            params.hexMap,
            params.units,
            params.allyPids);
}

}  // namespace shardok
