//
//  FleeCommand.cpp
//  eagle0
//
//  Created by Dan Crosby on 12/30/19.
//  Copyright © 2019 none. All rights reserved.
//

#include "FleeCommand.hpp"

#include <utility>

#include "src/main/cpp/net/eagle0/shardok/library/PercentileRollOdds.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/util/ActionResultFlatbufferHelpers.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/view_filters/OddsFilter.hpp"

namespace shardok {

auto FleeCommand::InternalExecute(
        const GameStateW& currentState,
        const std::shared_ptr<RandomGenerator>& generator) const -> vector<ActionResult> {
    const auto roll = generator->Percentile();
    return ExecuteWithRoll(currentState, roll);
}

[[nodiscard]] auto FleeCommand::ExecuteWithRoll(const GameStateW& currentState, const double roll)
        const -> vector<ActionResult> {
    ActionResult result{};
    result.mutable_player()->set_value(GetPlayerId());
    result.mutable_actor()->set_value(fleeingUnitId);

    const auto* fleeingUnit = currentState->units()->Get(fleeingUnitId);

    net::eagle0::shardok::storage::ResolvedUnit* resolvedUnit = result.add_resolved_units();
    AddUnitToResolved(*resolvedUnit, *fleeingUnit);

    if (fleeingUnit->attached_hero().is_vip() || PercentileRollSucceeds(successOdds, roll)) {
        result.set_type(net::eagle0::shardok::common::ActionType::FLED);
        resolvedUnit->set_status(net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_FLED_UNIT);
    } else {
        result.set_type(net::eagle0::shardok::common::ActionType::CAPTURED_WHILE_FLEEING);
        resolvedUnit->set_status(
                net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_CAPTURED_UNIT);
    }

    return {result};
}

FleeCommand::FleeCommand(
        const ActionCost& cost,
        const PlayerId playerId,
        const UnitId fleeingUnitId,
        PercentileRollOdds odds)
    : ShardokCommand(playerId),
      cost(cost),
      fleeingUnitId(fleeingUnitId),
      successOdds(std::move(odds)) {}

auto FleeCommand::GetCommandProto() const -> CommandProto {
    CommandProto proto;

    proto.set_player(GetPlayerId());
    proto.set_type(net::eagle0::shardok::common::FLEE_COMMAND);
    proto.mutable_actor()->set_value(fleeingUnitId);
    *proto.mutable_odds() = OddsFilteredForPlayer(successOdds, GetPlayerId());

    return proto;
}

auto FleeCommand::GetOddsPercentile() const -> int32_t {
    return OddsFilteredForPlayer(successOdds, GetPlayerId()).success_chance();
}
}  // namespace shardok
