#pragma once

#include <SDL2/SDL.h>
#include "ltexture.h"
#include <string>
#include <vector>

#ifndef UTILS_H
#define UTILS_H

// Dificultad del juego
#define DIFFICULTY_EASY 0
#define DIFFICULTY_NORMAL 1
#define DIFFICULTY_HARD 2

// Tipo de filtro
#define FILTER_NEAREST 0
#define FILTER_LINEAL 1

// 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;
};

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

// Estructura para mapear el teclado usado en la demo
struct demoKeys_t
{
	Uint8 left;
	Uint8 right;
	Uint8 noInput;
	Uint8 fire;
	Uint8 fireLeft;
	Uint8 fireRight;
};

// Estructura para albergar métodos de control
struct input_t
{
	int id;			  // Identificador en el vector de mandos
	std::string name; // Nombre del dispositivo
	Uint8 deviceType; // Tipo de dispositivo (teclado o mando)
};

// Estructura con todas las opciones de configuración del programa
struct options_t
{
	Uint8 difficulty;			// Dificultad del juego
	Uint8 playerSelected;		// Jugador seleccionado para el modo 1P
	std::vector<input_t> input; // Modo de control (teclado o mando)
	Uint8 language;				// Idioma usado en el juego
	Uint32 fullScreenMode;		// Contiene el valor del modo de pantalla completa
	Uint8 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 screenWidth;			// Ancho de la pantalla/ventana
	int screenHeight;			// Alto de la pantalla/ventana
	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
	float borderSize;			// Porcentaje de borde que se añade a lo ventana
};

// 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(std::string str);

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

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

#endif