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

#include "UpdateOpponentKnowledgeAction.hpp"

#include "src/main/cpp/net/eagle0/shardok/library/unit/Unit.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/util/ActionResultFlatbufferHelpers.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/util/PlayerUtils.hpp"

namespace shardok {

auto UpdateOpponentKnowledgeAction::InternalExecute(
        const GameStateW &currentState,
        const std::shared_ptr<RandomGenerator> &generator) const -> vector<ActionResult> {
    ActionResult result{};
    result.set_type(net::eagle0::shardok::common::ActionType::KNOWLEDGE_UPDATED);

    int attackerKnowledgeGain = settingsGetter.Backing().attacker_base_knowledge_gain();
    int defenderKnowledgeGain = settingsGetter.Backing().defender_base_knowledge_gain();
    int adjacentHeroKnowledgeGain = settingsGetter.Backing().adjacent_hero_knowledge_gain();

    const auto playerCount = currentState->player_infos()->size();

    for (const Unit *unit : *currentState->units()) {
        if (unit->hidden()) continue;
        if (unit->status() != net::eagle0::shardok::storage::fb::UnitStatus_NORMAL_UNIT) continue;
        PlayerId unitPid = unit->player_id();

        auto unitAfter = *unit;

        for (PlayerId pid = 0; pid < 10; pid++) {
            if (pid == unitPid) continue;
            if (pid >= playerCount) continue;
            int bump = PlayerIsDefender(currentState, pid) ? defenderKnowledgeGain
                                                           : attackerKnowledgeGain;
            MutatingBumpOpponentKnowledge(&unitAfter, pid, bump);
        }

        for (const Coords &adjCoords :
             HexMapUtils::GetAdjacentCoords(currentState->hex_map(), unit->location())) {
            const auto &occupantOptional = currentState.GetOccupant(adjCoords);
            if (occupantOptional && occupantOptional->player_id() != unitPid) {
                MutatingBumpOpponentKnowledge(
                        &unitAfter,
                        occupantOptional->player_id(),
                        adjacentHeroKnowledgeGain);
            }
        }

        AddChangedUnit(result, unitAfter);
    }

    if (result.changed_units_fb_size() == 0) return {};

    return {result};
}
}  // namespace shardok
