/*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_KEY_BIND_TAB
#define DEF_KEY_BIND_TAB

#include "Graphics/Drawable/Text.hpp"
#include "GUI/Widget/Tab.hpp"
#include "GUI/Widget/Chooser.hpp"
#include "GUI/Widget/TextButton.hpp"
#include "MultipleKeyBinder.hpp"
#include "Player/PlayerKeys.hpp"
#include <cstddef>
#include <map>
#include <string>

class Configuration;
class TextureManager;
class Font;
class SoundEngine;
struct JoystickData;

/// A tab interface to set the key bindings of a player
/// (of a given index).
class KeyBindTab : public Tab
{
    public:
        struct BinderData
        {
            BinderData() : resettable(false) {}
            BinderData(const std::string &name, const PlayerKeys &keys) :
            deviceName(name), defaultKeys(keys),
            resettable(!keys.allKeysUndefined()) {}

            std::string deviceName;
            PlayerKeys defaultKeys;
            bool resettable; ///< Whether reverting to defaultKeys is allowed
        };

        KeyBindTab(Configuration &configuration, std::size_t playerIx,
                   TextureManager &manager, Font &titleFont, Font &labelFont,
                   SoundEngine &soundEngine, float viewWidth);
        void draw() override;

        void addJoystickBinder(const JoystickData &joystickData);
        void removeJoystickBinder(int joystickID);

        bool mouseRelease(const Vector &mouseCoords) override;
        bool mouseClick(const Vector &mouseCoords) override;
        bool mouseMove(const Vector &mouseCoords) override;
        void keyEvent(const SDL_Event &event);

    private:
        void applyKeys();
        void applyActiveDevice();
        void adjustBinderPosition();
        void resetChooser();
        void unfocusBinders();

        const float m_viewWidth;

        /// Title message
        Text m_titleText, m_activeGameDeviceText;

        /// Chooser for joysticks
        Chooser m_deviceChooser;

        /// Game controller keys reset
        TextButton m_resetGameController;

        /// Key binders
        std::map<std::size_t, int> m_selectionToDevice;

        int m_currentDeviceID;
        std::map<int, BinderData> m_bindersData;
        std::map<int, MultipleKeyBinder> m_keyBinders;

        /// Resources
        Configuration *m_configuration;
        TextureManager *m_textureManager;
        Font *m_labelFont;
        SoundEngine *m_soundEngine;

        std::size_t m_playerIx;
};

#endif
