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

#ifndef EAGLE0_SHARDOK_LIBRARY_COMMANDS_MOVE_COMMAND_HPP
#define EAGLE0_SHARDOK_LIBRARY_COMMANDS_MOVE_COMMAND_HPP

#include "src/main/cpp/net/eagle0/shardok/library/BattalionType.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/ShardokCommand.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/map/CoordsSet.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/settings/GameSettings.hpp"
#include "src/main/flatbuffer/net/eagle0/shardok/storage/unit.hpp"
#include "src/main/protobuf/net/eagle0/shardok/common/command_type.pb.h"

namespace shardok {
using net::eagle0::shardok::common::MOVE_COMMAND;
using net::eagle0::shardok::storage::fb::Unit;
using Units = flatbuffers::Vector<const Unit*>;

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

    const ActionPoints pointCost;
    const UnitId moverId;
    const SettingsGetter settings;
    const vector<Coords> interimTargets;
    const vector<PlayerId> allyPids;
    std::unordered_set<CommandType> followUpCommandTypes;
    const bool willUnhide;
    const CoordsSet enemyZocCoords;

public:
    MoveCommand(
            ActionPoints pointCost,
            PlayerId playerId,
            UnitId moverId,
            const SettingsGetter& settingsGetter,
            vector<Coords> interimTargets,
            vector<PlayerId> allyPids,
            bool unhide,
            const CoordsSet& enemyZocCoords);

    ~MoveCommand() override = default;

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

    [[nodiscard]] auto GetCommandProto() const -> CommandProto override;

    [[nodiscard]] auto CanBeFollowUp() const -> bool override { return false; }
    [[nodiscard]] auto CanDoWithLowMorale() const -> bool override { return true; }

    void AddFollowUpCommandTypes(const std::unordered_set<CommandType>& newTypes) override;

    [[nodiscard]] int GetActorUnitId() const override { return moverId; }
    [[nodiscard]] MapIndex GetTargetRow() const override {
        return interimTargets.empty() ? -1 : interimTargets.back().row();
    }
    [[nodiscard]] MapIndex GetTargetColumn() const override {
        return interimTargets.empty() ? -1 : interimTargets.back().column();
    }
};
}  // namespace shardok

#endif  // EAGLE0_SHARDOK_LIBRARY_COMMANDS_MOVE_COMMAND_HPP
