#pragma once

#include <SDL3/SDL.h>

#include <cstdint>
#include <string>  // for string, basic_string
#include <vector>  // for vector

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

struct Animation {
    std::string name;              // Nombre de la animacion
    std::vector<SDL_Rect> frames;  // Cada uno de los frames que componen la animación
    int speed;                     // Velocidad de la animación
    int loop;                      // Indica a que frame vuelve la animación al terminar. -1 para que no vuelva
    bool completed;                // Indica si ha finalizado la animación
    int current_frame;             // Frame actual
    int counter;                   // Contador para las animaciones
};

struct AnimatedSpriteData {
    std::vector<Animation> animations;  // Vector con las diferentes animaciones
    Texture *texture;                   // Textura con los graficos para el sprite
};

// Carga la animación desde un fichero
auto loadAnimationFromFile(Texture *texture, const std::string &file_path, bool verbose = false) -> AnimatedSpriteData;

// Carga la animación desde bytes en memoria
auto loadAnimationFromMemory(Texture *texture, const std::vector<uint8_t> &bytes, const std::string &name_for_logs = "", bool verbose = false) -> AnimatedSpriteData;

class AnimatedSprite : public MovingSprite {
   public:
    explicit AnimatedSprite(Texture *texture = nullptr, SDL_Renderer *renderer = nullptr, const std::string &file = "", std::vector<std::string> *buffer = nullptr);  // Constructor
    AnimatedSprite(SDL_Renderer *renderer, AnimatedSpriteData *data);

    ~AnimatedSprite() override;  // Destructor

    void animate();                                              // Calcula el frame correspondiente a la animación actual
    auto getNumFrames() -> int;                                  // Obtiene el numero de frames de la animación actual
    void setCurrentFrame(int num);                               // Establece el frame actual de la animación
    void setAnimationCounter(const std::string &name, int num);  // Establece el valor del contador

    void setAnimationSpeed(const std::string &name, int speed);  // Establece la velocidad de una animación
    void setAnimationSpeed(int index, int speed);

    void setAnimationLoop(const std::string &name, int loop);  // Establece el frame al que vuelve la animación al finalizar
    void setAnimationLoop(int index, int loop);

    void setAnimationCompleted(const std::string &name, bool value);  // Establece el valor de la variable
    void setAnimationCompleted(int index, bool value);

    auto animationIsCompleted() -> bool;  // Comprueba si ha terminado la animación

    auto getAnimationClip(const std::string &name = "default", Uint8 index = 0) -> SDL_Rect;  // Devuelve el rectangulo de una animación y frame concreto
    auto getAnimationClip(int index_a = 0, Uint8 index_f = 0) -> SDL_Rect;

    auto getIndex(const std::string &name) -> int;                  // Obtiene el indice de la animación a partir del nombre
    auto loadFromVector(std::vector<std::string> *source) -> bool;  // Carga la animación desde un vector

    void setCurrentAnimation(const std::string &name = "default");  // Establece la animacion actual
    void setCurrentAnimation(int index = 0);

    void update() override;  // Actualiza las variables del objeto

    void setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h);  // OLD - Establece el rectangulo para un frame de una animación
    void setAnimationCounter(int value);                                                            // OLD - Establece el contador para todas las animaciones

    void resetAnimation();  // Reinicia la animación

   private:
    // Variables
    std::vector<Animation> animation_;  // Vector con las diferentes animaciones
    int current_animation_;             // Animacion activa
};
