#include "core/rendering/smartsprite.h"

#include "core/rendering/movingsprite.h"  // for MovingSprite
class Texture;

// Constructor
SmartSprite::SmartSprite(Texture *texture, SDL_Renderer *renderer) {
    // Copia punteros
    setTexture(texture);
    setRenderer(renderer);

    // Inicializa el objeto
    init();
}

// Inicializa el objeto
void SmartSprite::init() {
    enabled_ = false;
    enabled_counter_ = 0;
    on_destination_ = false;
    dest_x_ = 0;
    dest_y_ = 0;
    counter_ = 0;
    finished_ = false;
}

// Actualiza la posición y comprueba si ha llegado a su destino
void SmartSprite::update() {
    if (enabled_) {
        // Actualiza només la posició; els SmartSprite no usen animació de
        // frames i salten deliberadament AnimatedSprite::animate().
        // NOLINTNEXTLINE(bugprone-parent-virtual-call)
        MovingSprite::update();

        // Comprueba el movimiento
        checkMove();

        // Comprueba si ha terminado
        checkFinished();
    }
}

// Pinta el objeto en pantalla
void SmartSprite::render() {
    if (enabled_) {
        // Muestra el sprite por pantalla
        MovingSprite::render();
    }
}

// Obtiene el valor de la variable
auto SmartSprite::getEnabledCounter() const -> int {
    return enabled_counter_;
}

// Establece el valor de la variable
void SmartSprite::setEnabledCounter(int value) {
    enabled_counter_ = value;
}

// Establece el valor de la variable
void SmartSprite::setDestX(int x) {
    dest_x_ = x;
}

// Establece el valor de la variable
void SmartSprite::setDestY(int y) {
    dest_y_ = y;
}

// Obtiene el valor de la variable
auto SmartSprite::getDestX() const -> int {
    return dest_x_;
}

// Obtiene el valor de la variable
auto SmartSprite::getDestY() const -> int {
    return dest_y_;
}

// Comprueba el movimiento
void SmartSprite::checkMove() {
    // Comprueba si se desplaza en el eje X hacia la derecha
    if (getAccelX() > 0 || getVelX() > 0) {
        // Comprueba si ha llegado al destino
        if (getPosX() > dest_x_) {
            // Lo coloca en posición
            setPosX(dest_x_);

            // Lo detiene
            setVelX(0.0F);
            setAccelX(0.0F);
        }
    }
    // Comprueba si se desplaza en el eje X hacia la izquierda
    else if (getAccelX() < 0 || getVelX() < 0) {
        // Comprueba si ha llegado al destino
        if (getPosX() < dest_x_) {
            // Lo coloca en posición
            setPosX(dest_x_);

            // Lo detiene
            setVelX(0.0F);
            setAccelX(0.0F);
        }
    }

    // Comprueba si se desplaza en el eje Y hacia abajo
    if (getAccelY() > 0 || getVelY() > 0) {
        // Comprueba si ha llegado al destino
        if (getPosY() > dest_y_) {
            // Lo coloca en posición
            setPosY(dest_y_);

            // Lo detiene
            setVelY(0.0F);
            setAccelY(0.0F);
        }
    }
    // Comprueba si se desplaza en el eje Y hacia arriba
    else if (getAccelY() < 0 || getVelY() < 0) {
        // Comprueba si ha llegado al destino
        if (getPosY() < dest_y_) {
            // Lo coloca en posición
            setPosY(dest_y_);

            // Lo detiene
            setVelY(0.0F);
            setAccelY(0.0F);
        }
    }
}

// Comprueba si ha terminado
void SmartSprite::checkFinished() {
    // Comprueba si ha llegado a su destino
    on_destination_ = getPosX() == dest_x_ && getPosY() == dest_y_;

    if (on_destination_) {            // Si esta en el destino comprueba su contador
        if (enabled_counter_ == 0) {  // Si ha llegado a cero, deshabilita el objeto y lo marca como finalizado
            finished_ = true;
        } else {  // Si no ha llegado a cero, decrementa el contador
            enabled_counter_--;
        }
    }
}

// Obtiene el valor de la variable
auto SmartSprite::isOnDestination() const -> bool {
    return on_destination_;
}

// Obtiene el valor de la variable
auto SmartSprite::hasFinished() const -> bool {
    return finished_;
}