#pragma once

#include <SDL3/SDL.h>  // Para SDL_GamepadButton, SDL_Event, SDL_GamepadButtonEvent

#include <cstddef>  // Para size_t
#include <memory>   // Para shared_ptr
#include <string>   // Para basic_string, string
#include <utility>
#include <vector>  // Para vector

// Declaraciones adelantadas
class Input;
class Text;
enum class InputAction : int;

// Estructura para definir botones
struct DefineButtonsButton {
        std::string label;         // Texto en pantalla
        InputAction input;         // Acción asociada
        SDL_GamepadButton button;  // Botón del mando

        DefineButtonsButton(std::string lbl, InputAction inp, SDL_GamepadButton btn)
            : label(std::move(lbl)), input(inp), button(btn) {}
};

// Clase DefineButtons
class DefineButtons {
    public:
        DefineButtons();
        ~DefineButtons() = default;

        void render();                                                      // Dibuja el objeto en pantalla
        void checkEvents(const SDL_Event &event);                           // Procesa los eventos
        auto enable(int index_controller) -> bool;                          // Habilita la redefinición de botones
        [[nodiscard]] auto isEnabled() const -> bool { return enabled_; };  // Comprueba si está habilitado

    private:
        // Objetos
        Input *input_ = nullptr;      // Gestión de entrada
        std::shared_ptr<Text> text_;  // Renderizado de texto

        // Variables
        bool enabled_ = false;                       // Indica si está activo
        int x_ = 0, y_ = 0;                          // Coordenadas de texto
        std::vector<DefineButtonsButton> buttons_;   // Definiciones de botones
        size_t index_controller_ = 0;                // Índice del controlador asignado
        size_t index_button_ = 0;                    // Índice del botón en proceso
        std::vector<std::string> controller_names_;  // Nombres de los mandos
        bool finished_ = false;

        // Métodos internos
        void incIndexButton();                                             // Incrementa el índice de botones
        void doControllerButtonDown(const SDL_GamepadButtonEvent &event);  // Procesa pulsaciones
        void bindButtons();                                                // Asigna botones al sistema de entrada
        void saveBindingsToOptions();                                      // Guarda configuraciones
        auto checkButtonNotInUse(SDL_GamepadButton button) -> bool;        // Verifica uso de botones
        void clearButtons();                                               // Limpia asignaciones actuales
        void checkEnd();                                                   // Comprueba si ha finalizado
};
