#pragma once

#include <SDL3/SDL.h>  // Para SDL_FlipMode, SDL_FPoint, SDL_FRect

#include <memory>  // Para shared_ptr

#include "core/rendering/sprite/sprite.hpp"  // for Sprite

class Texture;

// --- Clase MovingSprite: añade movimiento y efectos de rotación, zoom y flip al sprite ---
class MovingSprite : public Sprite {
   public:
    // --- Estructuras ---
    struct Rotate {
        bool enabled{false};                      // Indica si ha de rotar
        double angle{0.0};                        // Ángulo para dibujarlo
        float amount{0.0F};                       // Cantidad de grados a girar en cada iteración
        SDL_FPoint center{.x = 0.0F, .y = 0.0F};  // Centro de rotación
    };

    // --- Constructores y destructor ---
    MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos, MovingSprite::Rotate rotate, float horizontal_zoom, float vertical_zoom, SDL_FlipMode flip);
    MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos);
    explicit MovingSprite(std::shared_ptr<Texture> texture);
    ~MovingSprite() override = default;

    // --- Métodos principales ---
    virtual void update(float delta_time);  // Actualiza las variables internas del objeto (time-based)
    void clear() override;                  // Reinicia todas las variables a cero
    void stop();                            // Elimina el movimiento del sprite
    void render() override;                 // Muestra el sprite por pantalla

    // --- Configuración ---
    void setPos(SDL_FRect rect);                                                                   // Establece la posición y el tamaño del objeto
    void setPos(float pos_x, float pos_y);                                                         // Establece la posición del objeto
    void setPosX(float pos_x);                                                                     // Establece la posición X
    void setPosY(float pos_y);                                                                     // Establece la posición Y
    void setVelX(float value) { vx_ = value; }                                                     // Establece la velocidad X
    void setVelY(float value) { vy_ = value; }                                                     // Establece la velocidad Y
    void setAccelX(float value) { ax_ = value; }                                                   // Establece la aceleración X
    void setAccelY(float value) { ay_ = value; }                                                   // Establece la aceleración Y
    void setHorizontalZoom(float value) { horizontal_zoom_ = value; }                              // Establece el zoom horizontal
    void setVerticalZoom(float value) { vertical_zoom_ = value; }                                  // Establece el zoom vertical
    void setAngle(double value) { rotate_.angle = value; }                                         // Establece el ángulo
    void setRotatingCenter(SDL_FPoint point) { rotate_.center = point; }                           // Establece el centro de rotación
    void setRotate(bool enable);                                                                   // Activa o desactiva el efecto de rotación
    void startRotate();                                                                            // Habilita la rotación con centro automático
    void stopRotate(float threshold = 0.0F);                                                       // Detiene la rotación y resetea ángulo
    void setRotateAmount(double value) { rotate_.amount = value; }                                 // Establece la velocidad de rotación
    void scaleRotateAmount(float value) { rotate_.amount *= value; }                               // Modifica la velocidad de rotacion
    void switchRotate() { rotate_.amount *= -1; }                                                  // Cambia el sentido de la rotación
    void setFlip(SDL_FlipMode flip) { flip_ = flip; }                                              // Establece el flip
    void flip() { flip_ = (flip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL; }  // Cambia el flip

    // --- Getters ---
    [[nodiscard]] auto getPosX() const -> float { return x_; }                 // Obtiene la posición X
    [[nodiscard]] auto getPosY() const -> float { return y_; }                 // Obtiene la posición Y
    [[nodiscard]] auto getVelX() const -> float { return vx_; }                // Obtiene la velocidad X
    [[nodiscard]] auto getVelY() const -> float { return vy_; }                // Obtiene la velocidad Y
    [[nodiscard]] auto getAccelX() const -> float { return ax_; }              // Obtiene la aceleración X
    [[nodiscard]] auto getAccelY() const -> float { return ay_; }              // Obtiene la aceleración Y
    [[nodiscard]] auto isRotating() const -> bool { return rotate_.enabled; }  // Verifica si está rotando
    auto getFlip() -> SDL_FlipMode { return flip_; }                           // Obtiene el flip

   protected:
    // --- Variables de estado ---
    Rotate rotate_;          // Variables usadas para controlar la rotación del sprite
    SDL_FlipMode flip_;      // Indica cómo se voltea el sprite
    float x_ = 0.0F;         // Posición en el eje X
    float y_ = 0.0F;         // Posición en el eje Y
    float vx_ = 0.0F;        // Velocidad en el eje X
    float vy_ = 0.0F;        // Velocidad en el eje Y
    float ax_ = 0.0F;        // Aceleración en el eje X
    float ay_ = 0.0F;        // Aceleración en el eje Y
    float horizontal_zoom_;  // Zoom aplicado a la anchura
    float vertical_zoom_;    // Zoom aplicado a la altura

    // --- Métodos internos ---
    void updateAngle() { rotate_.angle += rotate_.amount; }  // Incrementa el valor del ángulo
    void move(float delta_time);                             // Mueve el sprite según velocidad y aceleración (time-based)
    void rotate(float delta_time);                           // Rota el sprite según los parámetros de rotación (time-based)
};