#pragma once

#include <SDL3/SDL_rect.h>
#include <SDL3/SDL_render.h>
#include <SDL3/SDL_stdinc.h>
#include <memory>
#include <vector>

#include "options.h"
#include "param.h"
#include "utils.h"

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

constexpr int PLAY_AREA_HEIGHT = 200;

class Credits
{
public:
    Credits();
    ~Credits();

    void run(); // Bucle principal

private:
    // === 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
    SDL_Texture *canvas_;       // Textura donde dibujarlo 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;
    int mini_logo_final_pos_ = 0; // Posición final del minilogo

    // === 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 red_rect = play_area_; // Delimitador de ventana

    // === Métodos del Bucle Principal ===
    void update();      // Actualización principal
    void render();      // Renderizado
    void checkEvents(); // Manejo de eventos
    void checkInput();  // Procesamiento de entrada

    // === Métodos de Renderizado ===
    void fillTextTexture();       // Crear textura de texto
    void fillCanvas();            // Renderizar todos los sprites
    void updateTextureDstRects(); // Actualizar destinos de texturas

    // === 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

    // === Métodos de Interfaz ===
    void updateBlackRects(); // Actualizar rectángulos negros
    void updateRedRect();    // Actualizar rectángulo rojo

    // === Métodos de Audio ===
    void setVolume(int amount); // Establecer volumen
    void resetVolume();         // Restablecer volumen
};