#pragma once

#include <SDL2/SDL.h>
#include "texture.h"
#include <string>

#ifndef UTILS_H
#define UTILS_H

using namespace std;

// Estructura para definir un circulo
struct circle_t
{
	int x;
	int y;
	int r;
};

// Estructura para definir una linea horizontal
struct h_line_t
{
	int x1, x2, y;
};

// Estructura para definir una linea vertical
struct v_line_t
{
	int x, y1, y2;
};

// Estructura para definir una linea diagonal
struct d_line_t
{
	int x1, y1, x2, y2;
};

// Estructura para definir una linea
struct line_t
{
	int x1, y1, x2, y2;
};

// Estructura para definir un color
struct color_t
{
	Uint8 r;
	Uint8 g;
	Uint8 b;
};

// Tipos de paleta
enum palette_e
{
	p_zxspectrum,
	p_zxarne
};

// Posiciones de las notificaciones
enum not_pos_e
{
	pos_top,
	pos_bottom,
	pos_left,
	pos_middle,
	pos_right
};

// Tipos de control de teclado
enum ctrl_schem_e
{
	ctrl_cursor,
	ctrl_opqa,
	ctrl_wasd
};

// Estructura para las opciones de las notificaciones
struct op_notification_t
{
	not_pos_e posH; // Ubicación de las notificaciones en pantalla
	not_pos_e posV; // Ubicación de las notificaciones en pantalla
	bool sound;		// Indica si las notificaciones suenan
	color_t color;	// Color de las notificaciones
};

// Estructura para saber la seccion y subseccion del programa
struct section_t
{
	Uint8 name;
	Uint8 subsection;
};

// Estructura para albergar trucos
struct cheat_t
{
	bool infiniteLives; // Indica si el jugador dispone de vidas infinitas
	bool invincible;	// Indica si el jugador puede morir
	bool jailEnabled;	// Indica si la Jail está abierta
	bool altSkin;		// Indicxa si se usa una skin diferente para el jugador
};

// Estructura para el servicio online
struct online_t
{
	bool enabled;		 // Indica si se quiere usar el modo online o no
	bool sessionEnabled; // Indica ya se ha hecho login
	string server;		 // Servidor para los servicios online
	int port;			 // Puerto del servidor
	string gameID;		 // Identificador del juego para los servicios online
	string jailerID;	 // Identificador del jugador para los servicios online
	int score;			 // Puntuación almacenada online
};

// Estructura para almacenar estadísticas
struct op_stats_t
{
	int rooms;			   // Cantidad de habitaciones visitadas
	int items;			   // Cantidad de items obtenidos
	string worstNightmare; // Habitación con más muertes acumuladas
};

// Estructura con opciones de la pantalla
struct op_screen_t
{
	int windowWidth;  // Ancho de la ventana
	int windowHeight; // Alto de la ventana
};

// Estructura con todas las opciones de configuración del programa
struct options_t
{
	string configVersion;			 // Versión del programa. Sirve para saber si las opciones son compatibles
	Uint32 videoMode;				 // Contiene el valor del modo de pantalla completa
	int windowSize;					 // Contiene el valor por el que se multiplica el tamaño de la ventana
	Uint32 filter;					 // Filtro usado para el escalado de la imagen
	bool vSync;						 // Indica si se quiere usar vsync o no
	int gameWidth;					 // Ancho de la resolucion nativa del juego
	int gameHeight;					 // Alto de la resolucion nativa del juego
	bool integerScale;				 // Indica si el escalado de la imagen ha de ser entero en el modo a pantalla completa
	bool keepAspect;				 // Indica si se ha de mantener la relación de aspecto al poner el modo a pantalla completa
	bool borderEnabled;				 // Indica si ha de mostrar el borde en el modo de ventana
	int borderWidth;				 // Cantidad de pixels que se añade en el borde de la ventana
	int borderHeight;				 // Cantidad de pixels que se añade en el borde de la ventana
	palette_e palette;				 // Paleta de colores a usar en el juego
	bool console;					 // Indica si ha de mostrar información por la consola de texto
	cheat_t cheat;					 // Contiene trucos y ventajas para el juego
	op_stats_t stats;				 // Datos con las estadisticas de juego
	online_t online;				 // Datos del servicio online
	op_notification_t notifications; // Opciones relativas a las notificaciones;
	op_screen_t screen;				 // Opciones relativas a la clase screen
	ctrl_schem_e keys;				 // Teclas usadas para jugar
};

// Calcula el cuadrado de la distancia entre dos puntos
double distanceSquared(int x1, int y1, int x2, int y2);

// Detector de colisiones entre dos circulos
bool checkCollision(circle_t &a, circle_t &b);

// Detector de colisiones entre un circulo y un rectangulo
bool checkCollision(circle_t &a, SDL_Rect &b);

// Detector de colisiones entre un dos rectangulos
bool checkCollision(SDL_Rect &a, SDL_Rect &b);

// Detector de colisiones entre un punto y un rectangulo
bool checkCollision(SDL_Point &p, SDL_Rect &r);

// Detector de colisiones entre una linea horizontal y un rectangulo
bool checkCollision(h_line_t &l, SDL_Rect &r);

// Detector de colisiones entre una linea vertical y un rectangulo
bool checkCollision(v_line_t &l, SDL_Rect &r);

// Detector de colisiones entre una linea horizontal y un punto
bool checkCollision(h_line_t &l, SDL_Point &p);

// Detector de colisiones entre dos lineas
SDL_Point checkCollision(line_t &l1, line_t &l2);

// Detector de colisiones entre dos lineas
SDL_Point checkCollision(d_line_t &l1, v_line_t &l2);

// Detector de colisiones entre un punto y una linea diagonal
bool checkCollision(SDL_Point &p, d_line_t &l);

// Normaliza una linea diagonal
void normalizeLine(d_line_t &l);

// Devuelve un color_t a partir de un string
color_t stringToColor(palette_e pal, string str);

// Convierte una cadena en un valor booleano
bool stringToBool(string str);

// Convierte un valor booleano en una cadena
string boolToString(bool value);

// Compara dos colores
bool colorAreEqual(color_t color1, color_t color2);

// Inicializa la estructura de opciones
void initOptions(options_t *options);

#endif