#pragma once

#include <SDL3/SDL.h>

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

#include "core/rendering/sprite/animated_sprite.hpp"  // Para SurfaceAnimatedSprite

class Surface;

// Direcció de la dissolució
enum class DissolveDirection : std::uint8_t { NONE,
    DOWN,
    UP };

// Sprite que pot dissoldre's o generar-se de forma aleatòria en X mil·lisegons.
// progress_ va de 0.0 (totalment visible) a 1.0 (totalment invisible).
class DissolveSprite : public AnimatedSprite {
   public:
    explicit DissolveSprite(const AnimationResource& data);
    DissolveSprite(std::shared_ptr<Surface> surface, SDL_FRect pos);
    ~DissolveSprite() override = default;

    void update(float delta_time) override;
    void render() override;

    // Progrés manual [0.0 = totalment visible, 1.0 = totalment invisible]
    void setProgress(float progress);
    [[nodiscard]] auto getProgress() const -> float { return progress_; }

    // Inicia una dissolució temporal (visible → invisible en duration_ms)
    void startDissolve(float duration_ms, DissolveDirection dir = DissolveDirection::NONE);

    // Inicia una generació temporal (invisible → visible en duration_ms)
    void startGenerate(float duration_ms, DissolveDirection dir = DissolveDirection::NONE);

    void stopTransition();
    [[nodiscard]] auto isTransitionDone() const -> bool;

    // Substitució de color: en reconstruir, substitueix source per target
    void setColorReplace(Uint8 source, Uint8 target);

   private:
    enum class TransitionMode : std::uint8_t { NONE,
        DISSOLVING,
        GENERATING };

    std::shared_ptr<Surface> surface_display_;  // Superfície amb els píxels filtrats

    float progress_{0.0F};  // [0=visible, 1=invisible]
    DissolveDirection direction_{DissolveDirection::NONE};
    TransitionMode transition_mode_{TransitionMode::NONE};
    float transition_duration_{0.0F};
    float transition_elapsed_{0.0F};
    SDL_FRect prev_clip_{.x = 0, .y = 0, .w = 0, .h = 0};
    bool needs_rebuild_{false};
    Uint8 source_color_{255};  // 255 = transparent = sense replace per defecte
    Uint8 target_color_{0};

    void rebuildDisplaySurface();
    [[nodiscard]] static auto computePixelRank(int col, int row, int frame_h, DissolveDirection dir) -> float;
};
