#pragma once

#include <SDL3/SDL.h>

#include <array>    // Para std::array
#include <cstdint>  // Para uint8_t
#include <memory>   // Para shared_ptr
#include <string>   // Para string
#include <vector>   // Para vector

#include "game/scene_manager.hpp"  // Para SceneManager::Scene
#include "game/scenes/scene.hpp"   // Para Scene
#include "utils/delta_timer.hpp"   // Para DeltaTimer
class Sprite;                      // Forward declaration
class Surface;                     // Forward declaration
class Text;                        // Forward declaration

class Title : public Scene {
   public:
    // --- Constructor y Destructor ---
    Title();
    ~Title() override;

    // --- Bucle principal (SDL3 Callback API) ---
    void iterate() override;
    void handleEvent(const SDL_Event& event) override;

   private:
    // --- Estructuras y enumeraciones ---
    struct Glyph {
        uint32_t codepoint{0};  // Codepoint Unicode del carácter
        SDL_FRect clip{};       // Clip rect pre-calculado en el bitmap de fuente
        float x{0.0F};          // Posición en el eje x (float para precisión con delta time)
        float width{0.0F};      // Ancho pre-calculado del carácter
        bool enabled{false};    // Solo se escriben y mueven si estan habilitadas
    };

    enum class State : std::uint8_t {
        SHOW_LOADING_SCREEN,
        FADE_LOADING_SCREEN,
        MAIN_MENU,
        CHEEVOS_MENU,
        FADE_MENU,
        POST_FADE_MENU,
    };

    // --- Constantes de tiempo (en segundos) ---
    static constexpr float SHOW_LOADING_DURATION = 5.0F;          // Tiempo mostrando loading screen (antes 500 frames)
    static constexpr float FADE_STEP_INTERVAL = 0.05F;            // Intervalo entre pasos de fade (antes cada 4 frames)
    static constexpr float POST_FADE_DELAY = 1.0F;                // Delay después del fade (pantalla en negro)
    static constexpr float MAIN_MENU_IDLE_TIMEOUT = 20.0F;        // Timeout para ir a créditos (antes 2200 frames)
    static constexpr float KEYBOARD_REMAP_DISPLAY_DELAY = 2.0F;   // Tiempo mostrando teclas definidas antes de guardar
    static constexpr float MARQUEE_SPEED = 100.0F;                // Velocidad de marquesina (pixels/segundo)
    static constexpr float CHEEVOS_SCROLL_MAX_SPEED = 180.0F;     // Velocidad máxima de scroll de logros (pixels/segundo)
    static constexpr float CHEEVOS_SCROLL_ACCELERATION = 600.0F;  // Aceleración del scroll (pixels/segundo²)
    static constexpr float CHEEVOS_SCROLL_DECELERATION = 800.0F;  // Desaceleración del scroll (pixels/segundo²)

    // --- Constantes de marquesina ---
    static constexpr float MARQUEE_START_X = 256.0F;       // Posición inicial (ancho pantalla)
    static constexpr float MARQUEE_EXIT_X = -10.0F;        // Cuando desaparece de pantalla
    static constexpr float MARQUEE_Y = 184.0F;             // Posición Y
    static constexpr float MARQUEE_LETTER_SPACING = 1.0F;  // Espaciado entre letras

    // --- Métodos ---
    void update();                                                         // Actualiza las variables
    void render();                                                         // Dibuja en pantalla
    void handleMainMenuKeyPress(SDL_Keycode key);                          // Maneja las teclas del menu principal
    void handleInput(float delta_time);                                    // Comprueba las entradas
    void updateState(float delta_time);                                    // Actualiza el estado actual
    void transitionToState(State new_state);                               // Transiciona a un nuevo estado
    void updateShowLoadingScreen(float delta_time);                        // Actualiza SHOW_LOADING_SCREEN
    void updateFadeLoadingScreen(float delta_time);                        // Actualiza FADE_LOADING_SCREEN
    void updateMainMenu(float delta_time);                                 // Actualiza MAIN_MENU
    void updateCheevosMenu(float delta_time);                              // Actualiza CHEEVOS_MENU
    void updateFadeMenu(float delta_time);                                 // Actualiza FADE_MENU
    void updatePostFadeMenu(float delta_time);                             // Actualiza POST_FADE_MENU
    void initMarquee();                                                    // Inicializa la marquesina
    void updateMarquee(float delta_time);                                  // Actualiza la marquesina (time-based)
    void renderMarquee() const;                                            // Dibuja la marquesina
    void renderGameLogo();                                                 // Dibuja el logo con el titulo del juego
    void renderMainMenu();                                                 // Dibuja el menu principal
    void renderCheevosMenu();                                              // Dibuja el menu de logros
    void renderKeyboardRemap() const;                                      // Dibuja la pantalla de redefinir teclado
    void renderJoystickRemap() const;                                      // Dibuja la pantalla de redefinir joystick
    void handleKeyboardRemap(const SDL_Event& event);                      // Maneja la captura de teclas
    void handleJoystickRemap(const SDL_Event& event);                      // Maneja la captura de botones del gamepad
    static auto isKeyValid(SDL_Scancode scancode) -> bool;                 // Valida si una tecla es permitida
    auto isKeyDuplicate(SDL_Scancode scancode, int current_step) -> bool;  // Valida si una tecla esta duplicada
    auto isButtonDuplicate(int button, int current_step) -> bool;          // Valida si un boton esta duplicado
    void applyKeyboardRemap();                                             // Aplica y guarda las teclas redefinidas
    void applyJoystickRemap();                                             // Aplica y guarda los botones del gamepad redefinidos
    static auto getButtonName(int button) -> std::string;                  // Retorna el nombre amigable del boton del gamepad
    void createCheevosTexture();                                           // Crea y rellena la surface para mostrar los logros
    void resetCheevosScroll();                                             // Resetea el scroll de la lista de logros
    void fillTitleSurface();                                               // Dibuja los elementos en la surface

    // --- Variables miembro ---
    // Objetos y punteros
    std::shared_ptr<Surface> game_logo_surface_;       // Textura con los graficos
    std::unique_ptr<Sprite> game_logo_sprite_;         // SSprite para manejar la surface
    std::shared_ptr<Surface> loading_screen_surface_;  // Surface con los gráficos de la pantalla de carga
    std::unique_ptr<Sprite> loading_screen_sprite_;    // SSprite con los gráficos de la pantalla de carga
    std::shared_ptr<Surface> cheevos_surface_;         // Textura con la lista de logros
    std::unique_ptr<Sprite> cheevos_sprite_;           // SSprite para manejar la surface con la lista de logros
    std::shared_ptr<Surface> title_surface_;           // Surface donde se dibuja toda la clase
    std::unique_ptr<DeltaTimer> delta_timer_;          // Timer para delta time
    std::shared_ptr<Text> marquee_text_;               // Texto para marquesina
    std::shared_ptr<Text> menu_text_;                  // Texto para los menus

    // Variables de estado de marquesina
    std::string long_text_;       // Texto que aparece en la parte inferior del titulo
    std::vector<Glyph> letters_;  // Vector con las letras de la marquesina
    int first_active_letter_{0};  // Primera letra activa (optimización)
    int last_active_letter_{0};   // Última letra activa (optimización)

    // Variables de estado del menú de logros
    SDL_FRect cheevos_surface_view_;       // Zona visible de la surface con el listado de logros
    float cheevos_scroll_velocity_{0.0F};  // Velocidad actual del scroll de logros (pixels/segundo)

    // Variables de estado general
    State state_;                                                // Estado en el que se encuentra el bucle principal
    float state_time_{0.0F};                                     // Tiempo acumulado en el estado actual
    float fade_accumulator_{0.0F};                               // Acumulador para controlar el fade por tiempo
    SceneManager::Scene exit_scene_{SceneManager::Scene::GAME};  // Escena de destino al salir del título

    // Variables para redefinir controles
    bool is_remapping_keyboard_{false};      // True si estamos redefiniendo teclado
    bool is_remapping_joystick_{false};      // True si estamos redefiniendo joystick
    int remap_step_{0};                      // Paso actual en la redefinicion (0=LEFT, 1=RIGHT, 2=JUMP)
    std::array<SDL_Scancode, 3> temp_keys_;  // Almacenamiento temporal de teclas capturadas
    std::array<int, 3> temp_buttons_;        // Almacenamiento temporal de botones de gamepad capturados
    std::string remap_error_message_;        // Mensaje de error si la tecla/boton es invalido
    float axis_cooldown_{0.0F};              // Cooldown para evitar múltiples capturas de ejes
    bool remap_completed_{false};            // True cuando se completa el remap (mostrar antes de guardar)
};