/*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_LOBBY
#define DEF_CLIENT_LOBBY

#include "Graphics/Drawable/Sprite.hpp"
#include "GUI/LobbyCharacter.hpp"
#include "GUI/TextInputEnabler.hpp"
#include "GUI/Widget/TextButton.hpp"
#include "GUI/Widget/TextInput.hpp"
#include "GUI/Widget/Dialog.hpp"
#include "GUI/SectionHeader.hpp"
#include "GUI/PlaylistNotifier.hpp"
#include "Network/Host/Address.hpp"
#include "Network/Host/KickReason.hpp"

class Configuration;
class TextureManager;
class FontManager;
class SoundEngine;
class Viewport;
struct Vector;

/// Abstract class to extend in order to catch client lobby state callbacks
class ClientLobbyCallbackReceiver
{
    public:
        virtual ~ClientLobbyCallbackReceiver() {}
        virtual void lobbyConnectionRequestedCallback(const Address &address) = 0;
        virtual void lobbyConnectionCancelledCallback() = 0;
        virtual void lobbyExitRequestedCallback() = 0;
};

/// The game selection lobby lets the user select which server
/// to connect to, at which point it sends a callback to the Client.
/// It will keep being displayed and print updates while the connection
/// and handshake state with the server has not successfully completed.
class ClientLobby : public DialogCallbackReceiver
{
    public:
        ClientLobby(Configuration &configuration,
                    const Viewport &viewport,
                    TextureManager &textureManager,
                    FontManager &fontManager,
                    SoundEngine &soundEngine);
        ClientLobby(const ClientLobby &copied) = delete;
        ClientLobby &operator=(const ClientLobby &copied) = delete;
        ~ClientLobby();

        void setLobbyCallbackReceiver(ClientLobbyCallbackReceiver *receiver);

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

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

        /// The connection attempt has been cancelled by the user
        void dialogCancelledCallback() override;

        /// Notify the client lobby that the client is attempting a connection
        void switchToConnecting();

        /// Notify the client lobby that a game was disconnected for a \p reason
        void switchToDisconnected(KickReason reason);

        /// Returns the currently selected character for networked games
        const std::string &getCharacter() const;

    private:
        /// Check if the selected server address is valid and sends a callback
        /// to the Client which then initiates the connection
        bool requestConnection(const std::string &address,
                               const std::string &port,
                               const std::string &character);

        Configuration *m_configuration;
        ClientLobbyCallbackReceiver *m_callbackReceiver;
        std::string m_character;

        Sprite m_background;
        SectionHeader m_header;
        TextButton m_connect;
        LobbyCharacter m_characterChooser;

        TextInput m_addressInput, m_portInput, m_usernameInput;
        TextInputEnabler m_inputEnabler;

        Dialog m_connectionDialog, m_infoDialog;

        PlaylistNotifier m_notifier;
        const float m_addressPortGap;
};

#endif
