#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

#include "input.h"

// Clase DefineButtons
class DefineButtons {
    public:
        // Estructura para definir botones
        struct Button {
                std::string label;         // Texto en pantalla
                Input::Action action;      // Acción asociada
                SDL_GamepadButton button;  // Botón del mando

                Button(std::string label, Input::Action action, SDL_GamepadButton button)
                    : label(std::move(label)), action(action), button(button) {}
        };

        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

        // Variables
        bool enabled_ = false;                       // Indica si está activo
        int x_ = 0, y_ = 0;                          // Coordenadas de texto
        std::vector<Button> buttons_;                // Definiciones de botones
        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(std::shared_ptr<Input::Gamepad> gamepad);                                                // 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
};
