#pragma once

#include <SDL2/SDL_rect.h> // for SDL_Point
#include <functional>	   // for function
#include <memory>		   // for shared_ptr
#include <vector>		   // for vector
#include "sprite.h"		   // for Sprite
class Texture;			   // lines 8-8

enum class PathType
{
	VERTICAL,
	HORIZONTAL,
};

enum class PathCentered
{
	ON_X,
	ON_Y,
	NONE,
};

// Estructuras
struct Path
{
	std::vector<SDL_Point> spots; // Puntos por los que se desplazará el sprite
	int waiting_counter;		  // Tiempo de espera una vez en el destino
	bool on_destination = false;  // Indica si ha llegado al destino
	bool finished = false;		  // Indica si ha terminado de esperarse
	int counter = 0;			  // Contador interno

	// Constructor
	Path(const std::vector<SDL_Point> &spots_init, int waiting_counter_init)
		: spots(spots_init), waiting_counter(waiting_counter_init) {}
};

// Devuelve un vector con los puntos que conforman la ruta
std::vector<SDL_Point> createPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function<double(double)> &easingFunction);

// Clase PathSprite
class PathSprite : public Sprite
{
private:
	// Variables
	bool enabled_ = false;	  // Indica si el objeto está habilitado
	int current_path_ = 0;	  // Path que se está recorriendo actualmente
	std::vector<Path> paths_; // Caminos a recorrer por el sprite

	// Coloca el sprite en los diferentes puntos del recorrido
	void moveThroughCurrentPath();

	// Cambia de recorrido o finaliza
	void goToNextPathOrDie();

public:
	// Constructor
	explicit PathSprite(std::shared_ptr<Texture> texture)
		: Sprite(texture) {}

	// Destructor
	~PathSprite() = default;

	// Actualiza la posición del sprite
	void update();

	// Añade un recorrido
	void addPath(Path path, bool centered = false);
	void addPath(std::vector<SDL_Point> spots, int waiting_counter);
	void addPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function<double(double)> &easingFunction, int waiting_counter);

	// Habilita el objeto
	void enable();

	// Indica si ha terminado todos los recorridos
	bool hasFinished();
};