//
// Created by Dan Crosby on 4/10/20.
//

#include "ChallengeDuelCommandFactory.hpp"

#include "src/main/cpp/net/eagle0/shardok/library/commands/challenge_duel_command/ChallengeDuelCommand.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/unit/Unit.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/util/HexMapUtils.hpp"

namespace shardok {

void ChallengeDuelCommandFactory::AddAvailableChallengeDuelCommands(
        CommandList &existingCommands,
        const Unit *actingUnit,
        const Coords &position,
        const ActionPoints remainingActionPoints,
        const HexMap *map,
        const Units *units,
        const vector<PlayerId> &allyPids) const {
    if (actingUnit->has_attached_hero() &&
        actingUnit->attached_hero().profession_info().profession() ==
                net::eagle0::shardok::storage::fb::Profession_CHAMPION) {
        const auto costForDuel = ActionCost::UsesAllActionCost(
                settings.Backing().challenge_duel_action_point_cost());

        if (costForDuel.IsPossible(remainingActionPoints)) {
            for (const Coords &adjCoords : HexMapUtils::GetAdjacentCoords(map, position)) {
                // can't duel into a castle
                const auto *const destinationTerrain = GetTerrain(map, adjCoords);

                if (destinationTerrain->modifier().castle().present()) { continue; }

                const auto *enemyOccupant =
                        KnownEnemyOccupant(actingUnit->player_id(), units, allyPids, adjCoords);

                if (enemyOccupant) {
                    const auto *targetUnit = enemyOccupant;
                    if (targetUnit->has_attached_hero()
                        // Don't allow challenging an enemy to a duel if you know they don't have
                        // sufficient vigor
                        && (targetUnit->attached_hero().vigor() >=
                                    settings.Backing().minimum_vigor_to_accept_duel() ||
                            OpponentKnowledge(targetUnit, actingUnit->player_id()) <
                                    settings.Backing().minimum_knowledge_for_hero_stats())) {
                        existingCommands.emplace_back(std::make_shared<ChallengeDuelCommand>(
                                settings,
                                actingUnit->player_id(),
                                actingUnit->unit_id(),
                                targetUnit->unit_id(),
                                targetUnit->location(),
                                settings.Backing().minimum_knowledge_for_profession()));
                    }
                }
            }
        }
    }
}
void ChallengeDuelCommandFactory::AddAvailableCommands(
        CommandList &commands,
        const CommandFactory::CommandParams &params) const {
    AddAvailableChallengeDuelCommands(
            commands,
            params.unit,
            params.position,
            params.remainingActionPoints,
            params.hexMap,
            params.units,
            params.allyPids);
}

}  // namespace shardok
