//
//  ShardokAction.hpp
//  eagle0
//
//  Created by Dan Crosby on 11/30/14.
//  Copyright (c) 2014 none. All rights reserved.
//

#ifndef __eagle0__ShardokAction__
#define __eagle0__ShardokAction__

#include <vector>

#include "ShardokException.hpp"
#include "src/main/cpp/net/eagle0/common/RandomGenerator.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/GameStateW.hpp"
#include "src/main/protobuf/net/eagle0/shardok/storage/action_result.pb.h"

namespace shardok {

using net::eagle0::shardok::storage::ActionResult;
using std::shared_ptr;
using std::vector;
using PercentileRollOdds = net::eagle0::shardok::storage::Odds;

class IllegalActionException : public ShardokException {
    std::string description;

public:
    explicit IllegalActionException(const std::string& d) : ShardokException(d){};
};

// Encapsulates any action that changes game state
class ShardokAction {
private:
    // Most actions will override InternalExecute, but if an external roll is supported, they can
    // override that one and get the default behavior here.
    [[nodiscard]] virtual auto InternalExecute(
            const GameStateW& currentState,
            const std::shared_ptr<RandomGenerator>& generator) const -> std::vector<ActionResult> {
        return InternalExecuteWithRoll(currentState, generator, std::optional<int32_t>());
    }

    [[nodiscard]] virtual auto InternalExecuteWithRoll(
            const GameStateW& currentState,
            const std::shared_ptr<RandomGenerator>& generator,
            std::optional<int32_t> roll) const -> std::vector<ActionResult> {
        throw ShardokClientErrorException("Roll not supported");
    }

protected:
    ShardokAction() = default;

public:
    virtual ~ShardokAction() = default;

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

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

class ShardokAction;

typedef std::shared_ptr<ShardokAction> ActionSPtr;
typedef std::vector<ActionSPtr> ActionList;
}  // namespace shardok

#endif /* defined(__eagle0__ShardokAction__) */
