#pragma once

#include <SDL3/SDL.h>  // Para Uint32, Uint64

#include <memory>  // Para unique_ptr
#include <vector>  // Para vector

#include "color.hpp"        // Para Color
#include "param.hpp"        // Para Param, ParamIntro, param
#include "path_sprite.hpp"  // Para PathSprite
#include "tiled_bg.hpp"     // Para TiledBG
#include "writer.hpp"       // Para Writer

// --- Clase Intro: secuencia cinemática de introducción del juego ---
//
// Esta clase gestiona la secuencia de introducción narrativa del juego, mostrando
// una serie de escenas con imágenes, texto y efectos visuales sincronizados.
//
// Funcionalidades principales:
// • Sistema de escenas secuencial: 6 escenas con transiciones automáticas
// • Animaciones de tarjetas: efectos de entrada con diferentes tipos de easing
// • Texto narrativo: velocidades de escritura configurables por escena
// • Efectos visuales: sombras, bordes y transiciones de color
// • Audio sincronizado: música de fondo durante toda la secuencia
// • Estado POST: transición suave hacia el menú principal
//
// Todas las duraciones y velocidades están configuradas mediante constantes
// para facilitar el ajuste fino de la experiencia cinematográfica.

class Intro {
    public:
        // --- Constructor y destructor ---
        Intro();
        ~Intro() = default;

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

    private:
        // --- Constantes de tiempo (en segundos) ---
        static constexpr float TEXT_DISPLAY_DURATION_S = 3.0F;  // Duración de visualización de texto (180 frames a 60fps)
        static constexpr float POST_BG_STOP_DELAY_S = 1.0F;     // Retraso antes de detener el fondo
        static constexpr float POST_END_DELAY_S = 1.0F;         // Retraso antes de finalizar intro

        // --- Constantes de layout ---
        static constexpr float CARD_BORDER_SIZE = 2.0F;  // Tamaño del borde de tarjetas
        static constexpr float SHADOW_OFFSET = 8.0F;     // Desplazamiento de sombra
        static constexpr float TILED_BG_SPEED = 18.0F;   // Velocidad del fondo mosaico (pixels/segundo)
        static constexpr int TEXT_KERNING = -2;          // Espaciado entre caracteres

        // --- Constantes de velocidades de texto (segundos entre caracteres) ---
        static constexpr float TEXT_SPEED_NORMAL = 0.133F;      // Velocidad normal (8 frames * 16.67ms = 133ms)
        static constexpr float TEXT_SPEED_FAST = 0.2F;          // Velocidad rápida (12 frames * 16.67ms = 200ms)
        static constexpr float TEXT_SPEED_VERY_SLOW = 0.0167F;  // Velocidad muy lenta (1 frame * 16.67ms = 16.7ms)
        static constexpr float TEXT_SPEED_VERY_FAST = 0.267F;   // Velocidad muy rápida (16 frames * 16.67ms = 267ms)
        static constexpr float TEXT_SPEED_SLOW = 0.033F;        // Velocidad lenta (2 frames * 16.67ms = 33ms)
        static constexpr float TEXT_SPEED_MEDIUM_SLOW = 0.05F;  // Velocidad medio-lenta (3 frames * 16.67ms = 50ms)
        static constexpr float TEXT_SPEED_ULTRA_FAST = 0.333F;  // Velocidad ultra rápida (20 frames * 16.67ms = 333ms)

        // --- Constantes de animaciones de tarjetas (duraciones en segundos) ---
        static constexpr float CARD_ANIM_DURATION_NORMAL = 100.0F / 60.0F;     // ≈ 1.6667 s
        static constexpr float CARD_ANIM_DURATION_FAST = 40.0F / 60.0F;        // ≈ 0.6667 s
        static constexpr float CARD_ANIM_DURATION_MEDIUM = 70.0F / 60.0F;      // ≈ 1.1667 s
        static constexpr float CARD_ANIM_DURATION_SHORT = 80.0F / 60.0F;       // ≈ 1.3333 s
        static constexpr float CARD_ANIM_DURATION_SLOW = 250.0F / 60.0F;       // ≈ 4.1667 s
        static constexpr float CARD_ANIM_DURATION_VERY_SLOW = 300.0F / 60.0F;  // ≈ 5.0000 s

        static constexpr float CARD_ANIM_DELAY_LONG_S = 7.5F;  // Retraso largo antes de animación
        static constexpr float CARD_OFFSET_MARGIN = 10.0F;     // Margen fuera de pantalla

        // --- Estados internos ---
        enum class State {
            SCENES,
            POST,
        };

        enum class PostState {
            STOP_BG,
            END,
        };

        // --- Objetos ---
        std::vector<std::unique_ptr<PathSprite>> card_sprites_;    // Vector con los sprites inteligentes para los dibujos de la intro
        std::vector<std::unique_ptr<PathSprite>> shadow_sprites_;  // Vector con los sprites inteligentes para las sombras
        std::vector<std::unique_ptr<Writer>> texts_;               // Textos de la intro
        std::unique_ptr<TiledBG> tiled_bg_;                        // Fondo en mosaico

        // --- Variables ---
        Uint64 last_time_ = 0;                       // Último timestamp para calcular delta-time
        int scene_ = 0;                              // Indica qué escena está activa
        State state_ = State::SCENES;                // Estado principal de la intro
        PostState post_state_ = PostState::STOP_BG;  // Estado POST
        float state_start_time_;                     // Tiempo de inicio del estado actual (segundos)
        Color bg_color_ = param.intro.bg_color;      // Color de fondo

        // --- Métodos internos ---
        void update(float delta_time);         // Actualiza las variables del objeto
        void render();                         // Dibuja el objeto en pantalla
        static void checkInput();              // Comprueba las entradas
        static void checkEvents();             // Comprueba los eventos
        void updateScenes();                   // Actualiza las escenas de la intro
        void initSprites();                    // Inicializa las imágenes
        void initTexts();                      // Inicializa los textos
        void updateSprites(float delta_time);  // Actualiza los sprites
        void updateTexts(float delta_time);    // Actualiza los textos
        void renderSprites();                  // Dibuja los sprites
        void renderTexts();                    // Dibuja los textos
        static void renderTextRect();          // Dibuja el rectangulo de fondo del texto;
        void updatePostState();                // Actualiza el estado POST
        auto calculateDeltaTime() -> float;    // Calcula el tiempo transcurrido desde el último frame

        // --- Métodos para manejar cada escena individualmente ---
        void updateScene0();
        void updateScene1();
        void updateScene2();
        void updateScene3();
        void updateScene4();
        void updateScene5();

        // --- Métodos auxiliares para reducir duplicación de código ---
        void enableCardAndShadow(int index);
        void switchText(int from_index, int to_index);
};
