#pragma once

#include <SDL3/SDL.h>  // Para SDL_Keycode, SDL_Event, Uint64
#include <stdint.h>    // Para uint8_t

#include <memory>       // Para unique_ptr, shared_ptr
#include <string_view>  // Para string_view
#include <vector>       // Para vector

#include "section.hpp"  // Para Options, Name (ptr only)

class DefineButtons;
class Fade;
class GameLogo;
class Player;
class Sprite;
class Text;
class TiledBG;
namespace Options {
struct GamepadOptions;
}  // namespace Options
struct Color;

// Textos
constexpr std::string_view TEXT_COPYRIGHT = "@2020,2025 JailDesigner";

// Parámetros
constexpr bool ALLOW_TITLE_ANIMATION_SKIP = false;

/*
        Clase que gestiona el estado de título/menú principal del juego.
        Responsable de mostrar el logo, el fondo animado y gestionar la entrada para comenzar la partida.
        No permite saltar la animación del título salvo que se cambie el define.
*/

// Clase Title
class Title {
    public:
        // --- Constructor y destructor ---
        Title();
        ~Title();

        // --- Bucle principal ---
        void run();

    private:
        // --- Enumeraciones ---
        enum class TitleState {
            LOGO_ANIMATING,          // El logo está animándose
            LOGO_FINISHED,           // El logo ha terminado de animarse
            START_HAS_BEEN_PRESSED,  // Se ha pulsado el botón de start
        };

        // --- Estructura para definir anclas ---
        struct Anchor {
                int mini_logo;
                int copyright_text;
        };

        // --- Objetos y punteros ---
        std::shared_ptr<Text> text_;                     // Objeto de texto para escribir en pantalla
        std::unique_ptr<Fade> fade_;                     // Fundido en pantalla
        std::unique_ptr<TiledBG> tiled_bg_;              // Fondo animado de tiles
        std::unique_ptr<GameLogo> game_logo_;            // Logo del juego
        std::unique_ptr<Sprite> mini_logo_sprite_;       // Logo JailGames mini
        std::unique_ptr<DefineButtons> define_buttons_;  // Definición de botones del joystick
        std::vector<std::shared_ptr<Player>> players_;   // Vector de jugadores

        // --- Variables de estado ---
        int counter_ = 0;                                                // Temporizador para la pantalla de título
        Uint64 ticks_ = 0;                                               // Contador de ticks para ajustar la velocidad
        Section::Name next_section_;                                     // Siguiente sección a cargar
        Section::Options selection_ = Section::Options::TITLE_TIME_OUT;  // Opción elegida en el título
        int num_controllers_;                                            // Número de mandos conectados
        TitleState state_;                                               // Estado actual de la sección
        bool should_render_start_prompt_ = false;                        // Indica si se muestra o no el texto de PRESS START BUTTON TO PLAY
        bool player1_start_pressed_ = false;                             // Indica si se ha pulsdo el boton de empezar a jugar para el jugador 1
        bool player2_start_pressed_ = false;                             // Indica si se ha pulsdo el boton de empezar a jugar para el jugador 2

        // -- Variables de diseño ---
        Anchor anchor_;  // Anclas para definir la posición de los elementos del titulo

        // --- Ciclo de vida del título ---
        void update();                    // Actualiza las variables del objeto
        void updateState();               // Actualiza el estado actual del título
        void setState(TitleState state);  // Cambia el estado del título
        void resetCounter();              // Reinicia el contador interno

        // --- Entrada de usuario ---
        void checkEvents();                                                                                 // Comprueba los eventos
        void checkInput();                                                                                  // Comprueba las entradas
        void handleKeyDownEvent(const SDL_Event& event);                                                    // Maneja el evento de tecla presionada
        void handleControlKeys(SDL_Keycode key);                                                            // Maneja las teclas de control específicas
        [[nodiscard]] auto shouldSkipInputCheck() const -> bool;                                            // Determina si se debe omitir la comprobación de entrada
        void processControllerInputs();                                                                     // Procesa las entradas de los mandos
        [[nodiscard]] static auto isStartButtonPressed(const Options::GamepadOptions& controller) -> bool;  // Comprueba si se ha pulsado el botón Start
        void handleStartButtonPress(const Options::GamepadOptions& controller);                             // Maneja la pulsación del botón Start
        [[nodiscard]] auto canProcessStartButton() const -> bool;                                           // Verifica si se puede procesar la pulsación del botón Start
        void processPlayer1Start();                                                                         // Procesa el inicio del jugador 1
        void processPlayer2Start();                                                                         // Procesa el inicio del jugador 2
        void activatePlayerAndSetState(int player_id);                                                      // Activa al jugador y cambia el estado del título

        // --- Gestión de jugadores ---
        void initPlayers();                                 // Inicializa los jugadores
        void updatePlayers();                               // Actualiza los jugadores
        void renderPlayers();                               // Renderiza los jugadores
        auto getPlayer(int id) -> std::shared_ptr<Player>;  // Obtiene un jugador a partir de su "id"

        // --- Visualización / Renderizado ---
        void render();             // Dibuja el objeto en pantalla
        void updateFade();         // Actualiza el efecto de fundido (fade in/out)
        void updateStartPrompt();  // Actualiza el mensaje de "Pulsa Start"
        void renderStartPrompt();  // Dibuja el mensaje de "Pulsa Start" en pantalla
        void renderCopyright();    // Dibuja el aviso de copyright

        // --- Utilidades estáticas ---
        static void swapControllers();  // Intercambia la asignación de mandos a los jugadores
        static void swapKeyboard();     // Intercambia el teclado de jugador
        static void showControllers();  // Muestra información sobre los controles y los jugadores

// --- Depuración (solo en modo DEBUG) ---
#ifdef _DEBUG
        void handleDebugColorKeys(SDL_Keycode key);                       // Maneja las teclas de depuración para colores
        static void adjustColorComponent(SDL_Keycode key, Color& color);  // Ajusta un componente del color según la tecla
        static void incrementColorComponent(uint8_t& component);          // Incrementa un componente de color
        static void decrementColorComponent(uint8_t& component);          // Decrementa un componente de color
        static void incrementAllComponents(Color& color);                 // Incrementa todos los componentes del color
        static void decrementAllComponents(Color& color);                 // Decrementa todos los componentes del color
        static void printColorValue(const Color& color);                  // Imprime el valor actual del color en consola
#endif
};