/*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_SERVER_FIGHT_CONTROLLER
#define DEF_SERVER_FIGHT_CONTROLLER

#include "Fight/ServerFightScene.hpp"
#include "Network/Serialization/PeerData.hpp"

#ifdef HNMSERVER_DRAW
    #include "Engines/Resources/TextureManager.hpp"
#endif

class Referee;
class PlayerAction;
class DamageStatus;

struct PlayingPeerData
{
    PlayingPeerData() : player(nullptr) {}

    PlayingPeerData(const PeerData &peer,
                    ServerPlayerInterface *playerInterface) :
    peerData(peer), player(playerInterface) {}

    PeerData peerData;
    ServerPlayerInterface *player;
};

/// Handles a fight hosted by the server:
/// Receives player actions and produces fight status messages.
class ServerFightController
{
    public:
        explicit ServerFightController(FightRules::Mode mode,
                                       const std::string &arena);

        void setArena(const std::string &arenaName);

        void addPlayer(const PeerData &player);
        void removePlayer(std::size_t playerIx);

        void update(float frameTime);

        void applyAction(std::size_t playerIx, const PlayerAction &action);

        /// Let a referee observe the fight scene
        void showReferee(Referee &referee) const;

        /// Receive round instructions relayed from the server
        void readyRound();
        void startRound();

        /// Revive players (to ensure no KO players in lobby)
        void revivePlayers();

        std::vector<PlayerStatus> getPlayerStatus() const;
        std::vector<PhysicsObjectStatus> getPlatformStatus() const;
        std::vector<DamageStatus> getDamageStatus(
            const Timer::TimePoint &serverTime) const;
        EtherStatus getWeaponStatus() const;

    private:
        #ifdef HNMSERVER_DRAW
            TextureManager m_textureManager;
        #endif

        ServerFightScene m_fightScene;
        std::vector<PlayingPeerData> m_playingPeers;
};

#endif
