#pragma once

#include <SDL3/SDL_rect.h>	 // Para SDL_FRect, SDL_FPoint
#include <SDL3/SDL_render.h> // Para SDL_Renderer
#include <SDL3/SDL_stdinc.h> // Para Uint8
#include <stdint.h>			 // Para int32_t
#include <algorithm>		 // Para max, min
#include <string>			 // Para string
#include <vector>			 // Para vector

// --- Constantes ---
constexpr int BLOCK = 8;
constexpr int TOTAL_DEMO_DATA = 2000;

// --- Estructuras y tipos ---
struct Overrides
{
	std::string param_file;	   // Fichero de parametros a utilizar
	bool clear_hi_score_table; // Reinicia la tabla de records
	bool set_v_sync;		   // Establece el vsync

	Overrides()
		: param_file(""), clear_hi_score_table(false), set_v_sync(false) {}
};
extern Overrides overrides;

// Estructura para definir un circulo
struct Circle
{
	int x, y, r;
	Circle() : x(0), y(0), r(0) {}
	Circle(int xCoord, int yCoord, int radius)
		: x(xCoord), y(yCoord), r(radius) {}
};

// Estructura para definir un color
struct Color
{
	Uint8 r, g, b;
	constexpr Color() : r(0), g(0), b(0) {}
	explicit constexpr Color(int red, int green, int blue) : r(red), g(green), b(blue) {}

	constexpr Color getInverse() const { return Color(255 - r, 255 - g, 255 - b); }
	Color lighten(int amount = 50) const
	{
		return Color(
			std::min(255, r + amount),
			std::min(255, g + amount),
			std::min(255, b + amount));
	}
	Color darken(int amount = 50) const
	{
		return Color(
			std::max(0, r - amount),
			std::max(0, g - amount),
			std::max(0, b - amount));
	}
};

// Posiciones de las notificaciones
enum class NotifyPosition
{
	TOP,
	BOTTOM,
	LEFT,
	MIDDLE,
	RIGHT,
};

// Estructura para datos de la demo
struct DemoKeys
{
	Uint8 left;
	Uint8 right;
	Uint8 no_input;
	Uint8 fire;
	Uint8 fire_left;
	Uint8 fire_right;

	explicit DemoKeys(Uint8 l = 0, Uint8 r = 0, Uint8 ni = 0, Uint8 f = 0, Uint8 fl = 0, Uint8 fr = 0)
		: left(l), right(r), no_input(ni), fire(f), fire_left(fl), fire_right(fr) {}
};

using DemoData = std::vector<DemoKeys>;

struct Demo
{
	bool enabled;				// Indica si está activo el modo demo
	bool recording;				// Indica si está activado el modo para grabar la demo
	int counter;				// Contador para el modo demo
	DemoKeys keys;				// Variable con las pulsaciones de teclas del modo demo
	std::vector<DemoData> data; // Vector con diferentes sets de datos con los movimientos para la demo

	Demo() : enabled(false), recording(false), counter(0), keys(), data() {}
	Demo(bool e, bool r, int c, const DemoKeys &k, const std::vector<DemoData> &d)
		: enabled(e), recording(r), counter(c), keys(k), data(d) {}
};

// Posiciones dentro de un rectangulo
struct Zone
{
	SDL_FRect rect;		   // Rectangulo que define la zona
	float center_x;		   // Anclaje al 50% del eje X
	float first_quarter_x; // Anclaje al 25% del eje X
	float third_quarter_x; // Anclaje al 75% del eje X
	float center_y;		   // Anclaje al 50% del eje Y
	float first_quarter_y; // Anclaje al 25% del eje Y
	float third_quarter_y; // Anclaje al 75% del eje Y
};

// --- Funciones utilitarias ---

// Colores
extern const Color BG_COLOR;
extern const Color NO_COLOR;
extern const Color SHADOW_TEXT_COLOR;
extern const Color SEPARATOR_COLOR;
extern const Color SCOREBOARD_EASY_COLOR;
extern const Color SCOREBOARD_NORMAL_COLOR;
extern const Color SCOREBOARD_HARD_COLOR;
extern const Color FLASH_COLOR;
extern const Color FADE_COLOR;
extern const Color ORANGE_COLOR;
extern const Color ORANGE_SOFT_COLOR;
extern const Color GREEN_COLOR;
extern const Color BLUE_SKY_COLOR;
extern const Color PINK_SKY_COLOR;
extern const Color GREEN_SKY_COLOR;

// Colores y gráficos
Color getColorLikeKnightRider(const std::vector<Color> &colors, int counter_);

// Colisiones y geometría
double distanceSquared(int x1, int y1, int x2, int y2);
bool checkCollision(const Circle &a, const Circle &b);
bool checkCollision(const Circle &a, const SDL_FRect &b);
bool checkCollision(const SDL_FRect &a, const SDL_FRect &b);
bool checkCollision(const SDL_FPoint &p, const SDL_FRect &r);

// Conversión y manipulación de cadenas
bool stringToBool(const std::string &str);
std::string boolToString(bool value);
std::string boolToOnOff(bool value);
std::string toLower(const std::string &str);
std::string trim(const std::string &str);

// Dibujo
void DrawCircle(SDL_Renderer *renderer, int32_t centerX, int32_t centerY, int32_t radius);

// Manipulación de color
Color lightenColor(const Color &color, int amount);
Color DarkenColor(const Color &color, int amount);

// Funciones de suavizado (easing)
double easeOutQuint(double t);
double easeInQuint(double t);
double easeInOutQuint(double t);
double easeInQuad(double t);
double easeOutQuad(double t);
double easeInOutSine(double t);
double easeInOut(double t);
double easeInOutExpo(double t);
double easeOutBounce(double t);
double easeOutElastic(double t);
double easeInElastic(double t);

// Utilidades varias
bool stringInVector(const std::vector<std::string> &vec, const std::string &str);				  // Comprueba si un vector contiene una cadena
void printWithDots(const std::string &text1, const std::string &text2, const std::string &text3); // Imprime una línea con puntos

// Demo
DemoData loadDemoDataFromFile(const std::string &file_path);

#ifdef RECORDING
bool saveDemoFile(const std::string &file_path, const DemoData &dd);
#endif

// Ficheros y rutas
std::string getFileName(const std::string &path);  // Obtiene el nombre de un fichero a partir de una ruta
std::string getPath(const std::string &full_path); // Obtiene la ruta eliminando el nombre del fichero