//
// Created by Dan Crosby on 5/29/20.
//

#ifndef EAGLE0_FREEZEWATERCOMMAND_HPP
#define EAGLE0_FREEZEWATERCOMMAND_HPP

#include <optional>
#include <utility>

#include "src/main/cpp/net/eagle0/shardok/library/ShardokCommand.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/map/Coordinates.hpp"
#include "src/main/flatbuffer/net/eagle0/shardok/storage/terrain.hpp"
#include "src/main/flatbuffer/net/eagle0/shardok/storage/unit.hpp"

namespace shardok {

using Terrain = net::eagle0::shardok::storage::fb::Terrain;
using Unit = net::eagle0::shardok::storage::fb::Unit;

class FreezeWaterCommand : public ShardokCommand {
protected:
    [[nodiscard]] auto InternalExecute(
            const GameStateW& currentState,
            const std::shared_ptr<RandomGenerator>& generator) const
            -> vector<ActionResult> override;

    const ActionCost cost;
    const UnitId actorId;
    const Coords target;
    const Terrain* targetTerrain;
    const UnitId occupantId;
    const PercentileRollOdds odds;
    const int freezeWaterIntegrity;
    const int wisdomXp;
    const int minimumKnowledgeAfter;

public:
    FreezeWaterCommand(
            const ActionCost& cost,
            const Unit* actor,
            const Coords target,
            const Terrain* targetTerrain,
            const Unit* underwaterOccupant,
            PercentileRollOdds odds,
            const int freezeWaterIntegrity,
            const int wisdomXp,
            const int professionKnowledgeBump)
        : ShardokCommand(actor->player_id()),
          cost(cost),
          actorId(actor->unit_id()),
          target(target),
          targetTerrain(targetTerrain),
          occupantId(underwaterOccupant->unit_id()),
          odds(std::move(odds)),
          freezeWaterIntegrity(freezeWaterIntegrity),
          wisdomXp(wisdomXp),
          minimumKnowledgeAfter(professionKnowledgeBump){};

    FreezeWaterCommand(
            const ActionCost& cost,
            const Unit* actor,
            const Coords target,
            const Terrain* targetTerrain,
            PercentileRollOdds odds,
            const int freezeWaterIntegrity,
            const int wisdomXp,
            const int professionKnowledgeBump)
        : ShardokCommand(actor->player_id()),
          cost(cost),
          actorId(actor->unit_id()),
          target(target),
          targetTerrain(targetTerrain),
          occupantId(-1),
          odds(std::move(odds)),
          freezeWaterIntegrity(freezeWaterIntegrity),
          wisdomXp(wisdomXp),
          minimumKnowledgeAfter(professionKnowledgeBump){};

    ~FreezeWaterCommand() override = default;

    [[nodiscard]] auto ExecuteWithRoll(
            double roll,
            const GameStateW& currentState,
            const std::shared_ptr<RandomGenerator>& generator) const -> vector<ActionResult>;

    [[nodiscard]] auto GetCommandType() const -> CommandType override {
        return net::eagle0::shardok::common::FREEZE_WATER_COMMAND;
    }

    [[nodiscard]] auto GetCommandProto() const -> CommandProto override;
    [[nodiscard]] auto GetOccupantId() const -> UnitId { return occupantId; }

    [[nodiscard]] auto HasOdds() const -> bool override { return true; }
    [[nodiscard]] auto GetOddsPercentile() const -> int32_t override;
};
}  // namespace shardok

#endif  // EAGLE0_FREEZEWATERCOMMAND_HPP
