/*Copyright (C) 2010-2023 Duncan Deveaux

This file is part of Hikou no mizu.

Hikou no mizu is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Hikou no mizu is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Hikou no mizu.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef DEF_FIGHT_STATE
#define DEF_FIGHT_STATE

#include <vector>
#include <cstdint>
#include <cstddef>

/// Encodes the result of a round: Whether it is a draw,
/// and the winner index if it is not
struct RoundResult
{
    RoundResult() : drawGame(true), winnerIx(0) {}

    explicit RoundResult(std::size_t winner) :
    drawGame(false), winnerIx(winner) {}

    bool drawGame;
    std::size_t winnerIx;
};

/// Encodes the current state of a game/fight, i.e., the phase of the fight
/// such as fighting or in an end-of-round break, and the round win statistics
class FightState
{
    public:
        enum class Phase : std::uint8_t
        {
            /// Ready to kick off a fight, players are ready but cannot move yet
            Ready = 0,
            Fighting = 1, ///< Fighting in a round

            /// Short break at the end of a round, with more remaining
            Break = 2,
            Finished = 3 ///< All rounds have been completed
        };

        explicit FightState(std::size_t playerCount = 0);
        FightState(Phase phase, unsigned int roundId,
                   const RoundResult &lastResult,
                   const std::vector<std::uint8_t> &winsPerPlayer);

        void setToReady();
        void setToFighting();
        void finishDraw();

        /// Declare a winner to the current round, and update the phase
        /// accordingly to either Phase::Break or Phase::Finished
        /// Returns the updated cumulated number of rounds won by \p winnerIx
        std::uint8_t finishWinner(std::size_t winnerIx,
                                  std::uint8_t roundsToWin);

        /// Notify that a player was erased mid-game
        /// (when a playing peer disconnects)
        bool playerWasErased(std::size_t playerIx);

        Phase getPhase() const;
        const RoundResult &getLastRoundResult() const;
        const std::vector<std::uint8_t> &getWinsPerPlayer() const;

        /// Returns the current round id based on the previous wins statistics
        unsigned int getRoundId() const;

    private:
        Phase m_phase; ///< The current phase of the fight: ready, fighting, ...
        unsigned int m_roundId; ///< The current round number

        /// The result of the last round if any (draw game otherwise by default)
        RoundResult m_lastResult;

        /// Number of rounds won per player index:
        /// The n^th element refers to the n^th player in the fight
        std::vector<std::uint8_t> m_winsPerPlayer;
};

#endif
