#pragma once

#include <SDL3/SDL_rect.h>   // Para SDL_FRect
#include <SDL3/SDL_render.h> // Para SDL_Renderer, SDL_Texture
#include "utils.h"

// Modos de funcionamiento para el tileado de fondo
enum class TiledBGMode : int
{
    CIRCLE = 0,
    DIAGONAL = 1,
    RANDOM = 2,
    STATIC = 3,
};

/*
    Esta clase dibuja un tileado de fondo. Para ello se sirve de una textura "canvas", que rellena con los tiles.
    El rectángulo "window" recorre la textura de diferentes formas para generar el efecto de movimiento de la
    textura en pantalla.
*/

// Clase TiledBG
class TiledBG
{
public:
    // --- Constructores y destructor ---
    TiledBG(SDL_FRect pos, TiledBGMode mode);
    ~TiledBG();

    // --- Métodos principales ---
    void render(); // Pinta la clase en pantalla
    void update(); // Actualiza la lógica de la clase

    // --- Configuración ---
    void setSpeed(float speed) { speed_ = speed; }                                             // Establece la velocidad
    void stopGracefully() { stopping_ = true; }                                                // Detiene el desplazamiento de forma ordenada
    void setColor(Color color) { SDL_SetTextureColorMod(canvas_, color.r, color.g, color.b); } // Cambia el color de la textura

    // --- Getters ---
    bool isStopped() const { return speed_ == 0.0f; } // Indica si está parado

private:
    // --- Constantes ---
    static constexpr int TILE_WIDTH_ = 64;  // Ancho del tile
    static constexpr int TILE_HEIGHT_ = 64; // Alto del tile

    // --- Objetos y punteros ---
    SDL_Renderer *renderer_; // El renderizador de la ventana
    SDL_Texture *canvas_;    // Textura donde dibujar el fondo formado por tiles

    // --- Variables de estado ---
    SDL_FRect pos_;         // Posición y tamaño del mosaico
    SDL_FRect window_;      // Ventana visible para la textura de fondo del título
    TiledBGMode mode_;      // Tipo de movimiento del mosaico
    double sin_[360];       // Vector con los valores del seno precalculados
    float desp_ = 0.0f;     // Desplazamiento aplicado
    float speed_ = 1.0f;    // Incremento que se añade al desplazamiento a cada bucle
    bool stopping_ = false; // Indica si se está deteniendo

    // --- Métodos internos ---
    void fillTexture();                    // Rellena la textura con el contenido
    void updateDesp() { desp_ += speed_; } // Actualiza el desplazamiento
    void updateStop();                     // Detiene el desplazamiento de forma ordenada
};