#pragma once

#include <SDL3/SDL_events.h>  // Para SDL_Event, SDL_GamepadButtonEvent
#include <SDL3/SDL_gamepad.h> // Para SDL_GamepadButton
#include <memory>             // Para std::shared_ptr
#include <stddef.h>           // Para size_t
#include <string>             // Para std::string
#include <vector>             // Para std::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(const std::string &lbl, InputAction inp, SDL_GamepadButton btn)
        : label(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
    bool enable(int index_controller);        // Habilita la redefinición de botones
    bool isEnabled() const;                   // 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

    // 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
    bool checkButtonNotInUse(SDL_GamepadButton button);               // Verifica uso de botones
    void clearButtons();                                              // Limpia asignaciones actuales
};
