#pragma once

#include <SDL3/SDL_rect.h>    // Para SDL_FPoint, SDL_FRect
#include <SDL3/SDL_surface.h> // Para SDL_FlipMode
#include <algorithm>          // Para std::max
#include <memory>             // Para shared_ptr
#include "sprite.h"           // Para Sprite

class Texture;

// Clase MovingSprite. Añade movimiento y efectos de rotación, zoom y flip al sprite
class MovingSprite : public Sprite
{
public:
    // --- Estructura para la rotación ---
    struct Rotate
    {
        bool enabled;      // Indica si ha de rotar
        int counter;       // Contador
        int speed;         // Velocidad de giro
        double angle;      // Ángulo para dibujarlo
        float amount;      // Cantidad de grados a girar en cada iteración
        SDL_FPoint center; // Centro de rotación

        Rotate() : enabled(false), counter(0), speed(1), angle(0.0), amount(0.0f), center({0.0f, 0.0f}) {}
    };

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

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

    // --- Getters de posición y movimiento ---
    float getPosX() const { return x_; }
    float getPosY() const { return y_; }
    float getVelX() const { return vx_; }
    float getVelY() const { return vy_; }
    float getAccelX() const { return ax_; }
    float getAccelY() const { return ay_; }

    // --- Setters de movimiento ---
    void setVelX(float value) { vx_ = value; }
    void setVelY(float value) { vy_ = value; }
    void setAccelX(float value) { ax_ = value; }
    void setAccelY(float value) { ay_ = value; }

    // --- Rotación ---
    bool isRotating() const { return rotate_.enabled; }
    void setZoomW(float value) { zoom_w_ = value; }
    void setZoomH(float value) { zoom_h_ = value; }
    void setAngle(double value) { rotate_.angle = value; }
    void setRotatingCenter(SDL_FPoint point) { rotate_.center = point; }
    void setRotate(bool enable); // Activa o desactiva el efecto de rotación
    void setRotateSpeed(int value) { rotate_.speed = std::max(1, value); }
    void setRotateAmount(double value) { rotate_.amount = value; }
    void switchRotate() { rotate_.amount *= -1; } // Cambia el sentido de la rotación

    // --- Flip ---
    void setFlip(SDL_FlipMode flip) { flip_ = flip; }
    void flip() { flip_ = (flip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL; }
    SDL_FlipMode getFlip() { return flip_; }

    // --- Posición y tamaño ---
    void setPos(SDL_FRect rect);   // Establece la posición y el tamaño del objeto
    void setPos(float x, float y); // Establece la posición del objeto
    void setPosX(float value);     // Establece la posición X
    void setPosY(float value);     // Establece la posición Y

protected:
    // --- Variables de posición y movimiento ---
    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. Cantidad de píxeles a desplazarse
    float vy_ = 0.0f; // Velocidad en el eje Y. Cantidad de píxeles a desplazarse

    float ax_ = 0.0f; // Aceleración en el eje X. Variación de la velocidad
    float ay_ = 0.0f; // Aceleración en el eje Y. Variación de la velocidad

    // --- Efectos visuales ---
    Rotate rotate_;     // Variables usadas para controlar la rotación del sprite
    float zoom_w_;      // Zoom aplicado a la anchura
    float zoom_h_;      // Zoom aplicado a la altura
    SDL_FlipMode flip_; // Indica cómo se voltea el sprite

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