#pragma once

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

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

#include "color.h"    // Para Zone, Color
#include "options.h"  // Para AudioOptions, MusicOptions, audio
#include "param.h"    // Para Param, ParamGame, param
#include "utils.h"

// Declaraciones adelantadas
class BalloonManager;
class Fade;
class Player;
class TiledBG;

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

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

    private:
        // --- Constantes de clase ---
        static constexpr int PLAY_AREA_HEIGHT = 200;

        // --- Objetos principales ---
        std::unique_ptr<BalloonManager> balloon_manager_;  // Gestión de globos
        std::unique_ptr<TiledBG> tiled_bg_;                // Mosaico animado de fondo
        std::unique_ptr<Fade> fade_in_;                    // Fundido de entrada
        std::unique_ptr<Fade> fade_out_;                   // Fundido de salida
        std::vector<std::shared_ptr<Player>> players_;     // Vector de jugadores

        // --- Gestión de texturas ---
        SDL_Texture *text_texture_;  // Textura con el texto de créditos
        SDL_Texture *canvas_;        // Textura donde se dibuja todo

        // --- Temporización y contadores ---
        Uint64 ticks_ = 0;                    // Control de velocidad del programa
        Uint32 counter_ = 0;                  // Contador principal de lógica
        Uint32 counter_pre_fade_ = 0;         // Activación del fundido final
        Uint32 counter_prevent_endless_ = 0;  // Prevención de bucle infinito

        // --- Variables de estado ---
        bool fading_ = false;                 // Estado del fade final
        bool want_to_pass_ = false;           // Jugador quiere saltarse créditos
        bool mini_logo_on_position_ = false;  // Minilogo en posición final

        // --- Diseño y posicionamiento ---
        float black_bars_size_ = (param.game.game_area.rect.h - PLAY_AREA_HEIGHT) / 2;  // Tamaño de las barras negras
        int mini_logo_final_pos_ = 0;                                                   // Posición final del minilogo
        Color color_;                                                                   // Color usado para los efectos

        // --- Control de audio ---
        int initial_volume_ = Options::audio.music.volume;  // Volumen inicial
        int steps_ = 0;                                     // Pasos para reducir audio

        // --- Rectángulos de renderizado ---
        // Texto de créditos
        SDL_FRect credits_rect_src_ = param.game.game_area.rect;
        SDL_FRect credits_rect_dst_ = param.game.game_area.rect;

        // Mini logo
        SDL_FRect mini_logo_rect_src_ = param.game.game_area.rect;
        SDL_FRect mini_logo_rect_dst_ = param.game.game_area.rect;

        // Definición del área de juego
        SDL_FRect play_area_ = {
            param.game.game_area.rect.x,
            param.game.game_area.rect.y + black_bars_size_,
            param.game.game_area.rect.w,
            PLAY_AREA_HEIGHT};

        // Barras negras para efecto letterbox
        SDL_FRect top_black_rect_ = {
            play_area_.x,
            param.game.game_area.rect.y,
            play_area_.w,
            black_bars_size_};
        SDL_FRect bottom_black_rect_ = {
            play_area_.x,
            param.game.game_area.rect.h - black_bars_size_,
            play_area_.w,
            black_bars_size_};
        SDL_FRect left_black_rect_ = {
            play_area_.x,
            param.game.game_area.center_y - 1,
            0,
            2};
        SDL_FRect right_black_rect_ = {
            play_area_.x + play_area_.w,
            param.game.game_area.center_y - 1,
            0,
            2};

        // Borde para la ventana
        SDL_FRect border_rect_ = play_area_;  // Delimitador de ventana

        // --- Métodos del bucle principal ---
        void update();              // Actualización principal de la lógica
        void render();              // Renderizado de la escena
        static void checkEvents();  // Manejo de eventos
        void checkInput();          // Procesamiento de entrada

        // --- Métodos de renderizado ---
        void fillTextTexture();        // Crear textura de texto de créditos
        void fillCanvas();             // Renderizar todos los sprites y fondos
        void updateTextureDstRects();  // Actualizar destinos de texturas
        void renderPlayers();          // Renderiza los jugadores

        // --- Métodos de lógica del juego ---
        void throwBalloons();   // Lanzar globos al escenario
        void initPlayers();     // Inicializar jugadores
        void updateAllFades();  // Actualizar estados de fade
        void cycleColors();     // Cambiar colores de fondo
        void updatePlayers();   // Actualza los jugadores

        // --- Métodos de interfaz ---
        void updateBlackRects();  // Actualizar rectángulos negros (letterbox)
        void updateRedRect();     // Actualizar rectángulo rojo (borde)

        // --- Métodos de audio ---
        static void setVolume(int amount);  // Establecer volumen
        void resetVolume() const;           // Restablecer volumen
};