#include "core/rendering/sprite/moving_sprite.hpp"

#include <utility>

#include "core/rendering/surface.hpp"  // Para Surface

// Constructor
MovingSprite::MovingSprite(std::shared_ptr<Surface> surface, SDL_FRect pos, SDL_FlipMode flip)
    : Sprite(std::move(surface), pos),
      x_(pos.x),
      y_(pos.y),
      flip_(flip) { Sprite::pos_ = pos; }

MovingSprite::MovingSprite(std::shared_ptr<Surface> surface, SDL_FRect pos)
    : Sprite(std::move(surface), pos),
      x_(pos.x),
      y_(pos.y) { Sprite::pos_ = pos; }

MovingSprite::MovingSprite() { Sprite::clear(); }

MovingSprite::MovingSprite(std::shared_ptr<Surface> surface)
    : Sprite(std::move(surface)) { Sprite::clear(); }

// Reinicia todas las variables
void MovingSprite::clear() {
    // Resetea posición
    x_ = 0.0F;
    y_ = 0.0F;

    // Resetea velocidad
    vx_ = 0.0F;
    vy_ = 0.0F;

    // Resetea aceleración
    ax_ = 0.0F;
    ay_ = 0.0F;

    // Resetea flip
    flip_ = SDL_FLIP_NONE;

    Sprite::clear();
}

// Mueve el sprite (time-based)
// Nota: vx_, vy_ ahora se interpretan como pixels/segundo
// Nota: ax_, ay_ ahora se interpretan como pixels/segundo²
void MovingSprite::move(float delta_time) {
    // Aplica aceleración a velocidad (time-based)
    vx_ += ax_ * delta_time;
    vy_ += ay_ * delta_time;

    // Aplica velocidad a posición (time-based)
    x_ += vx_ * delta_time;
    y_ += vy_ * delta_time;

    // Actualiza posición entera para renderizado
    pos_.x = static_cast<int>(x_);
    pos_.y = static_cast<int>(y_);
}

// Actualiza las variables internas del objeto (time-based)
void MovingSprite::update(float delta_time) {
    move(delta_time);
}

// Muestra el sprite por pantalla
void MovingSprite::render() {
    surface_->render(pos_.x, pos_.y, &clip_, flip_);
}

// Muestra el sprite por pantalla
void MovingSprite::render(Uint8 source_color, Uint8 target_color) {
    surface_->renderWithColorReplace(pos_.x, pos_.y, source_color, target_color, &clip_, flip_);
}

// Establece la posición y_ el tamaño del objeto
void MovingSprite::setPos(SDL_FRect rect) {
    x_ = rect.x;
    y_ = rect.y;

    pos_ = rect;
}

// Establece el valor de las variables
void MovingSprite::setPos(float x, float y) {
    x_ = x;
    y_ = y;

    pos_.x = static_cast<int>(x_);
    pos_.y = static_cast<int>(y_);
}

// Establece el valor de la variable
void MovingSprite::setPosX(float value) {
    x_ = value;
    pos_.x = static_cast<int>(x_);
}

// Establece el valor de la variable
void MovingSprite::setPosY(float value) {
    y_ = value;
    pos_.y = static_cast<int>(y_);
}