//
// Created by sebastian on 02.08.26.
//

#ifndef COLORRACE_LUDOGAMEMODE_H
#define COLORRACE_LUDOGAMEMODE_H
#include <memory>
#include <optional>
#include <random>

#include "DiceSource.h"
#include "LudoGameState.h"
#include "LudoTypes.h"
#include "core/events/EventBus.h"
#include "game/TurnBasedGameMode.h"
#include "gameMode/LudoRules.h"

namespace ludo {

    class LudoGameMode: public engine::TurnBasedGameMode<LudoCommand, LudoEvent, LudoGameState> {
    public:
        explicit LudoGameMode(engine::EventBus<LudoEvent>& eventBus, std::vector<engine::PlayerID> players, std::optional<unsigned int> seed = std::nullopt) : TurnBasedGameMode(std::move(players)),
            m_diceSource(std::make_unique<RandomDiceSource>()), m_gameState(getPlayerOrder()), m_eventBus(eventBus) {}
        void sendCommand(const std::variant<MovePieceCommand, RollDiceCommand> &command) override;
        std::vector<LudoEvent> pollEvents() override;


        [[nodiscard]] const LudoGameState& getState() const override { return m_gameState; }
        [[nodiscard]] PlayerColor getColorOf(engine::PlayerID playerID) const;
        void setDiceSource(std::unique_ptr<IDiceSource> diceSource) { m_diceSource = std::move(diceSource); }
    private:
        engine::EventBus<LudoEvent>& m_eventBus;


        LudoRules::MoveResult movePieceInternal(int pieceIndex, int diceValue);
        void autoReleasePiece(int pieceIndex);

        void handle(const RollDiceCommand &command);

        void handle(const MovePieceCommand &command);
        void finishTurn();


        LudoGameState m_gameState;
        std::vector<LudoEvent> m_pendingEvents;

        int rollDice();
        std::unique_ptr<IDiceSource> m_diceSource;

        void publishEvent(LudoEvent event);
    };
}


#endif //COLORRACE_LUDOGAMEMODE_H
