#pragma once

#include <SDL3/SDL_rect.h>   // Para SDL_FRect
#include <SDL3/SDL_stdinc.h> // Para Uint16
#include <memory>            // Para shared_ptr, unique_ptr
#include <string>            // Para string
#include <vector>            // Para vector
#include "animated_sprite.h" // Para AnimatedSprite
#include "utils.h"           // Para Circle

class Texture;

// Tipos de objetos disponibles en el juego.
// Define los diferentes tipos de objetos que pueden existir en el juego.
enum class ItemType : int
{
    DISK = 1,           // Disco
    GAVINA = 2,         // Gavina
    PACMAR = 3,         // Pacman
    CLOCK = 4,          // Reloj
    COFFEE = 5,         // Café
    DEBIAN = 6,         // Debian
    COFFEE_MACHINE = 7, // Máquina de café
    NONE = 8,           // Ninguno
};

// Clase Item.
// Representa un objeto en el juego, con sus propiedades y métodos para gestionar su comportamiento.
class Item
{
public:
    // Constructor. Inicializa un objeto Item con el tipo, posición, área de juego, textura y animación.
    Item(ItemType type, float x, float y, SDL_FRect &play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation);

    // Destructor.
    ~Item() = default;

    // Centra el objeto en la posición X indicada, asegurando que no se salga del área de juego.
    void alignTo(int x);

    // Renderiza el objeto en pantalla si está habilitado.
    // Si el tiempo de vida es mayor que 200, renderiza el sprite.
    // Si es menor o igual a 200, renderiza el sprite de forma intermitente.
    void render();

    // Desactiva el objeto estableciendo su estado enabled_ a false.
    void disable();

    // Actualiza la posición, animación y contadores del objeto.
    // Llama a move(), sprite_->update() y updateTimeToLive().
    void update();

    // Getters
    float getPosX() const { return pos_x_; }
    float getPosY() const { return pos_y_; }
    int getWidth() const { return width_; }
    int getHeight() const { return height_; }
    ItemType getType() const { return type_; }
    bool isEnabled() const { return enabled_; }
    bool isOnFloor() const { return floor_collision_; }
    Circle &getCollider() { return collider_; }

private:
    // Objetos y punteros
    std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos del objeto

    // Variables de estado y físicas
    float pos_x_;                  // Posición X del objeto
    float pos_y_;                  // Posición Y del objeto
    int width_;                    // Ancho del objeto
    int height_;                   // Alto del objeto
    float vel_x_;                  // Velocidad en el eje X
    float vel_y_;                  // Velocidad en el eje Y
    float accel_x_ = 0.0f;         // Aceleración en el eje X
    float accel_y_;                // Aceleración en el eje Y
    bool floor_collision_ = false; // Indica si el objeto colisiona con el suelo
    ItemType type_;                // Tipo de objeto
    bool enabled_ = true;          // Indica si el objeto está habilitado
    Circle collider_;              // Círculo de colisión del objeto
    SDL_FRect play_area_;          // Rectángulo con la zona de juego
    Uint16 time_to_live_ = 600;    // Tiempo que el objeto está presente

    // Alinea el círculo de colisión con la posición del objeto.
    // Actualiza las coordenadas X e Y del colisionador.
    void shiftColliders();

    // Coloca el sprite en la posición del objeto.
    // Actualiza las coordenadas X e Y del sprite.
    void shiftSprite();

    // Actualiza la posición y estados del objeto.
    // Controla las colisiones con los límites del área de juego y actualiza sprite y colisionador.
    void move();

    // Actualiza el contador de tiempo de vida del objeto.
    // Si el tiempo de vida es mayor a 0, lo decrementa. Si llega a 0, desactiva el objeto.
    void updateTimeToLive();
};
