#pragma once

#include <cstdint>  // Para uint8_t
#include <memory>   // Para shared_ptr
#include <vector>   // Para vector

class Surface;

// Efecto de revelado pixel a pixel por filas, de arriba a abajo.
// Cada fila se revela en num_steps pasos, con píxeles en orden aleatorio u ordenado (bisección).
class PixelReveal {
   public:
    // Modo de revelado: aleatorio por fila o en orden de bisección (dithering ordenado 1D)
    enum class RevealMode : std::uint8_t { RANDOM,
        ORDERED };

    // Constructor
    PixelReveal(int width, int height, float pixels_per_second, float step_duration, int num_steps = 4, bool reverse = false, RevealMode mode = RevealMode::RANDOM);

    ~PixelReveal() = default;

    // Actualiza el estado del revelado según el tiempo transcurrido
    void update(float time_active);

    // Dibuja la máscara de revelado en la posición indicada
    void render(int dst_x, int dst_y) const;

    // Indica si el revelado ha completado todas las filas
    [[nodiscard]] auto isComplete() const -> bool;

   private:
    std::shared_ptr<Surface> cover_surface_;      // Máscara negra que se va haciendo transparente
    std::vector<std::vector<int>> reveal_order_;  // Orden de columnas por fila (aleatorio u ordenado por bisección)
    std::vector<int> row_step_;                   // Paso actual de revelado por fila (0..num_steps_)
    int width_;
    int height_;
    float pixels_per_second_;  // Filas reveladas por segundo
    float step_duration_;      // Segundos por paso dentro de una fila
    int num_steps_;            // Número de pasos de revelado por fila
    bool reverse_;             // Si true: transparente → negro (ocultar); si false: negro → transparente (revelar)
    RevealMode mode_;          // Modo de revelado: aleatorio u ordenado por bisección
};
