#pragma once

#include <SDL3/SDL.h>

#include "core/rendering/sprite.h"  // for Sprite
class Texture;

// Clase MovingSprite. Añade posicion y velocidad en punto flotante
class MovingSprite : public Sprite {
   public:
    explicit MovingSprite(float x = 0, float y = 0, int w = 0, int h = 0, float velx = 0, float vely = 0, float accelx = 0, float accely = 0, Texture *texture = nullptr, SDL_Renderer *renderer = nullptr);  // Constructor

    void move();             // Mueve el sprite
    void rotate();           // Rota el sprite
    virtual void update();   // Actualiza las variables internas del objeto
    void clear();            // Reinicia todas las variables
    void render() override;  // Muestra el sprite por pantalla

    // cppcheck-suppress duplInheritedMember
    [[nodiscard]] auto getPosX() const -> float;  // Obten el valor de la variable
    // cppcheck-suppress duplInheritedMember
    [[nodiscard]] auto getPosY() const -> float;  // Obten el valor de la variable

    [[nodiscard]] auto getVelX() const -> float;          // Obten el valor de la variable
    [[nodiscard]] auto getVelY() const -> float;          // Obten el valor de la variable
    [[nodiscard]] auto getAccelX() const -> float;        // Obten el valor de la variable
    [[nodiscard]] auto getAccelY() const -> float;        // Obten el valor de la variable
    [[nodiscard]] auto getZoomW() const -> float;         // Obten el valor de la variable
    [[nodiscard]] auto getZoomH() const -> float;         // Obten el valor de la variable
    [[nodiscard]] auto getAngle() const -> double;        // Obten el valor de la variable
    [[nodiscard]] auto getRotate() const -> bool;         // Obtiene el valor de la variable
    [[nodiscard]] auto getRotateSpeed() const -> Uint16;  // Obtiene el valor de la variable

    void setRect(SDL_Rect rect) override;  // Establece la posición y el tamaño del objeto
    void setPosX(float value);             // Establece el valor de la variable
    void setPosY(float value);             // Establece el valor de la variable
    void setVelX(float value);             // Establece el valor de la variable
    void setVelY(float value);             // Establece el valor de la variable
    void setAccelX(float value);           // Establece el valor de la variable
    void setAccelY(float value);           // Establece el valor de la variable
    void setZoomW(float value);            // Establece el valor de la variable
    void setZoomH(float value);            // Establece el valor de la variable
    void setAngle(double value);           // Establece el valor de la variable
    void incAngle(double value);           // Incrementa el valor de la variable
    void decAngle(double value);           // Decrementa el valor de la variable

    void setRotate(bool value);          // Establece el valor de la variable
    void setRotateSpeed(int value);      // Establece el valor de la variable
    void setRotateAmount(double value);  // Establece el valor de la variable
    void disableRotate();                // Quita el efecto de rotación y deja el sprite en su angulo inicial.
    void switchRotate();                 // Cambia el sentido de la rotación

    void setFlip(SDL_FlipMode flip);  // Establece el valor de la variable
    void flip();                      // Gira el sprite horizontalmente
    auto getFlip() -> SDL_FlipMode;   // Obtiene el valor de la variable

    auto getRect() -> SDL_Rect override;  // Devuelve el rectangulo donde está el sprite

    void undoMove();   // Deshace el último movimiento
    void undoMoveX();  // Deshace el último movimiento en el eje X
    void undoMoveY();  // Deshace el último movimiento en el eje Y
    void clearVel();   // Pone a cero las velocidades de desplacamiento

    [[nodiscard]] auto getIncX() const -> int;  // Devuelve el incremento en el eje X en pixels

   protected:
    // cppcheck-suppress duplInheritedMember
    float x_;  // Posición en el eje X (sub-pixel; Sprite::x_ es int)
    // cppcheck-suppress duplInheritedMember
    float y_;  // Posición en el eje Y (sub-pixel; Sprite::y_ es int)

    float x_prev_;  // Posición anterior en el eje X
    float y_prev_;  // Posición anterior en el eje Y

    float vx_;  // Velocidad en el eje X. Cantidad de pixeles a desplazarse
    float vy_;  // Velocidad en el eje Y. Cantidad de pixeles a desplazarse

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

    float zoom_w_{1};  // Zoom aplicado a la anchura
    float zoom_h_{1};  // Zoom aplicado a la altura

    double angle_{0.0};                         // Angulo para dibujarlo
    bool rotate_enabled_{false};                // Indica si ha de rotar
    int rotate_speed_{0};                       // Velocidad de giro
    double rotate_amount_{0.0};                 // Cantidad de grados a girar en cada iteración
    int counter_{0};                            // Contador interno
    SDL_Point *center_{nullptr};                // Centro de rotación
    SDL_FlipMode current_flip_{SDL_FLIP_NONE};  // Indica como se voltea el sprite
};
