/*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_CLIENT_GAME
#define DEF_CLIENT_GAME

#include "Network/Host/ClientHost.hpp" ///< ClientHost::MessageReceiver
#include "Network/Client/ClientFightController.hpp"
#include "Network/Client/ClientPauseTab.hpp"
#include "Network/Serialization/PlayerAction.hpp"
#include "GUI/Fight/NameTags.hpp"
#include "GUI/Fight/EventLogger.hpp"
#include "GUI/Fight/FightInterface.hpp"
#include "GUI/Fight/RoundAnnouncer.hpp"
#include "GUI/Fight/RoundResultInfo.hpp"
#include "GUI/Fight/PeerInfoLayer.hpp"
#include "GUI/Fight/FpsCounter.hpp"
#include "Engines/Resources/TextureManager.hpp"
#include "Engines/Resources/FontManager.hpp"
#include "Engines/Resources/SoundBufferManager.hpp"
#include "Engines/Sound/AmbientPlayer.hpp"
#include "Engines/Sound/SoundEngine.hpp"
#include "Graphics/Camera.hpp"
#include "Structs/Vector.hpp"
#include "Tools/Timer.hpp"
#include <vector>
#include <string>

class JoystickManager;
class Configuration;
class GameMetadata;
class ServerHandshakeMessage;
class GameStateMessage;
class PeerPingMessage;

class ClientGame : public ClientHost::MessageReceiver,
                   public PlayerActionSender
{
    public:
        ClientGame(ClientHost &host,
                   JoystickManager &joystickManager,
                   const Configuration &configuration,
                   const Vector &viewSize);

        void reset(); ///< Reset the game state, useful when disconnecting

        /// Called when a connection to a server was established
        void initialize(const std::string &characterName);

        void messageReceivedCallback(const ENetPacket &packet,
                                     Channel channel) override;

        void sendPlayerAction(PlayerAction::Index actionIx) override;

        void mouseMove(const Vector &viewCoords);
        void mouseRelease(const Vector &viewCoords);
        void keyEvent(const SDL_Event &event);

        void update();
        void draw(float frameTime);

    private:
        void processHandshake(const ServerHandshakeMessage &message);
        void processGameMetadata(const GameMetadata &game, bool initialUpdate);
        void processGameState(const GameStateMessage &message);
        void processPeerPing(const PeerPingMessage &message);
        void processUnintelligible();

        ClientHost *m_host;
        const Configuration *m_configuration;

        TextureManager m_textureManager;
        FontManager m_fontManager;
        SoundBufferManager m_soundBufferManager;
        AmbientPlayer m_ambientPlayer;
        SoundEngine m_soundEngine;

        ClientFightController m_fightController;
        Timer m_clock;

        /// Clock ticks that the last update represents
        Timer::duration_uint64_us m_lastUpdate;

        /// Whether a server update was just applied: The client is up to date,
        /// do not predict future states by calling update() for that frame
        bool m_appliedUpdate;

        /// Whether the current fight was already announced.
        /// Useful to avoid showing the 'FIGHT' announcement twice, e.g.,
        /// when a player disconnects mid-game
        bool m_announcedFight;

        /// Whether an initial game state was received from the server
        /// Useful to initially synchronize client and server clocks,
        /// and change the music to signal joining the game
        bool m_hasInitialGameState;

        /// Whether to draw the peer information layer
        bool m_showPeerInfo;

        ClientPauseTab m_pauseDialog;
        NameTags m_nameTags;
        EventLogger m_eventLogger;
        OptionalFpsCounter m_fpsCounter;
        FightInterface m_fightInterface;
        PeerInfoLayer m_peerInfoLayer;
        RoundAnnouncer m_roundAnnouncer;
        RoundResultInfo m_roundResultInfo;
        const Camera m_interfaceCamera;
        const Vector m_viewSize;

        std::string m_requestedCharacter;
};

#endif
