#pragma once

#include <SDL2/SDL_gamecontroller.h> // Para SDL_GameControllerButton
#include <SDL2/SDL_stdinc.h>		 // Para Uint8
#include "manage_hiscore_table.h"
#include <vector> // Para vector
#include "input.h"
#include <string>
enum class InputType : int;
enum class ScreenFilter : int;
enum class ScreenVideoMode : int;
namespace lang
{
	enum class Code : int;
}

// Dificultad del juego
enum class GameDifficulty
{
	EASY = 0,
	NORMAL = 1,
	HARD = 2,
};

// Estructura para las opciones de la ventana
struct OptionsWindow
{
	int size; // Contiene el valor por el que se multiplica el tamaño de la ventana
};

// Estructura con opciones para el video
struct OptionsVideo
{
	OptionsWindow window; // Opciones para la ventana del programa
	ScreenVideoMode mode; // Contiene el valor del modo de pantalla completa
	ScreenFilter filter;  // Filtro usado para el escalado de la imagen
	bool v_sync;		  // Indica si se quiere usar vsync o no
	bool integer_scale;	  // Indica si se va a usar el escalado entero
	bool shaders;		  // Indica si se van a usar shaders para los filtros de video
};

// Estructura para las opciones de musica
struct OptionsMusic
{
	bool enabled; // Indica si la musica suena o no
	int volume;	  // Volumen al que suena la música
};

// Estructura para las opciones de sonido
struct OptionsSound
{
	bool enabled; // Indica si los sonidos suenan o no
	int volume;	  // Volumen al que suenan los sonidos
};

// Estructura para las opciones de audio
struct OptionsAudio
{
	OptionsMusic music; // Opciones para la música
	OptionsSound sound; // Opciones para los efectos de sonido
	bool enabled;		// Indica si el audio está activo o no
	int volume;			// Volumen al que suenan el audio
};

// Estructura para las opciones del juego
struct OptionsGame
{
	GameDifficulty difficulty;				  // Dificultad del juego
	lang::Code language;					  // Idioma usado en el juego
	bool autofire;							  // Indica si el jugador ha de pulsar repetidamente para disparar o basta con mantener pulsado
	std::vector<HiScoreEntry> hi_score_table; // Tabla con las mejores puntuaciones
};

// Estructura para los controles del juego
struct OptionsController
{
	int index;									   // Indice en el vector de mandos
	int player_id;								   // Jugador asociado al mando
	InputDeviceToUse type;									   // Indica si se utilizará teclado o mando o ambos
	std::string name;							   // Nombre del dispositivo
	bool plugged;								   // Indica si el mando se encuentra conectado
	std::vector<InputType> inputs;				   // Listado de inputs
	std::vector<SDL_GameControllerButton> buttons; // Listado de botones asignados a cada input

	// Constructor por defecto
	OptionsController()
		: index(-1), player_id(-1), type(InputDeviceToUse::CONTROLLER), name(""), plugged(false)
	{
		inputs = {InputType::FIRE_LEFT, InputType::FIRE_CENTER, InputType::FIRE_RIGHT, InputType::START, InputType::SERVICE};
		buttons = {SDL_CONTROLLER_BUTTON_X, SDL_CONTROLLER_BUTTON_Y, SDL_CONTROLLER_BUTTON_B, SDL_CONTROLLER_BUTTON_START, SDL_CONTROLLER_BUTTON_BACK};
	}
};

// Estructura con todas las opciones de configuración del programa
struct Options
{
	OptionsGame game;							// Opciones para el propio juego
	OptionsVideo video;							// Opciones relativas a la clase screen
	OptionsAudio audio;							// Opciones para el audio
	std::vector<OptionsController> controllers; // Opciones con las asignaciones del mando para cada jugador
};

// Variables
extern Options options;

void initOptions();

// Carga el fichero de configuración
bool loadOptionsFile(std::string file_path);

// Guarda el fichero de configuración
bool saveOptionsFile(std::string file_path);

// Convierte valores de 0 a 100 en valores de 0 a 128
int to_JA_volume(int vol);

// Asigna el teclado al jugador
void setKeyboardToPlayer(int player_id);

// Intercambia el teclado de jugador
void swapOptionsKeyboard();

// Intercambia los jugadores asignados a los dos primeros mandos
void swapOptionsControllers();

// Averigua quien está usando el teclado
int getPlayerWhoUsesKeyboard();