//
// Created by Dan Crosby on 2/15/21.
//

#include "StartFireCommandFactory.hpp"

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

namespace shardok {

auto StartFireCommandFactory::MakeStartFireCommand(
        const Unit *unit,
        const Coords &coords,
        const Terrain &targetTerrain,
        const PercentileRollOdds &odds) const -> shardok::CommandSPtr {
    return std::make_shared<StartFireCommand>(settings, unit, coords, targetTerrain, odds);
}

StartFireCommandFactory::StartFireCommandFactory(const shardok::SettingsGetter &getter)
    : settings(getter) {}

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

    if (unit->can_start_fire()) {
        const ActionCost cost =
                ActionCost::UsesAllActionCost(settings.Backing().start_fire_action_point_cost());

        if (cost.IsPossible(remainingActionPoints)) {
            for (const Coords &adjCoords : HexMapUtils::GetAdjacentCoords(hexMap, position)) {
                if (GetTerrain(hexMap, adjCoords)->modifier().fire().present()) { continue; }

                const auto &occupantOptional =
                        FriendlyOccupant(playerId, units, allyPids, adjCoords);
                if (!occupantOptional) {
                    const auto *const targetTerrain = GetTerrain(hexMap, adjCoords);
                    PercentileRollOdds odds = GetStartFireOdds(
                            settings,
                            *targetTerrain,
                            *weather,
                            hero.agility(),
                            hero.wisdom(),
                            hero.profession_info().profession() ==
                                    net::eagle0::shardok::storage::fb::Profession_MAGE);
                    if (GetSuccessChance(odds) > 0.01) {
                        commands.push_back(
                                MakeStartFireCommand(unit, adjCoords, *targetTerrain, odds));
                    }
                }
            }
        }
    }
}
void StartFireCommandFactory::AddAvailableCommands(
        CommandList &commands,
        const CommandParams &params) const {
    AddAvailableStartFireCommands(
            commands,
            params.unit,
            params.units,
            params.allyPids,
            params.hexMap,
            params.remainingActionPoints,
            params.position,
            params.weatherFb);
}
}  // namespace shardok
