#pragma once

#include <SDL2/SDL.h>
#include "common/asset.h"
#include "common/input.h"
#include "common/jail_audio.h"
#include "common/menu.h"
#include "common/movingsprite.h"
#include "common/screen.h"
#include "common/smartsprite.h"
#include "common/sprite.h"
#include "common/text.h"
#include "common/utils.h"
#include "const.h"
#include "fade.h"
#include "game.h"
#include "enter_id.h"
#include "hiscore_table.h"
#include "instructions.h"
#include "item.h"

#ifndef TITLE_H
#define TITLE_H

// Textos
#define TEXT_COPYRIGHT "@2020,2023 JailDesigner (v2.3)"

// Contadores
#define TITLE_COUNTER 800

// Cantidad de eventos de la pantalla de titulo
#define TITLE_TOTAL_EVENTS 2

class Title
{
private:
	struct menu_t
	{
		Menu *title;		// Menu de la pantalla de título
		Menu *options;		// Menú de la pantalla de opciones
		Menu *playerSelect; // Menu para elegir jugador
		Menu *active;		// Menu activo (de momento para la pantalla del titulo)
		bool keyPressed;	// Variable para evitar la repetición de teclas en los menus
	};

	// Objetos y punteros
	SDL_Renderer *renderer;		// El renderizador de la ventana
	Screen *screen;				// Objeto encargado de dibujar en pantalla
	Asset *asset;				// Objeto que gestiona todos los ficheros de recursos
	Input *input;				// Objeto para leer las entradas de teclado o mando
	Lang *lang;					// Objeto para gestionar los textos en diferentes idiomas
	Instructions *instructions; // Objeto para la sección de las instrucciones
	HiScoreTable *hiScoreTable; // Objeto para mostrar las mejores puntuaciones online
	Game *demoGame;				// Objeto para lanzar la demo del juego
	EnterID *enterID;			// Objeto para introducir o modificar el JailerID
	SDL_Event *eventHandler;	// Manejador de eventos
	section_t *section;			// Indicador para el bucle del titulo

	Texture *dustTexture;	  // Textura con los graficos del polvo
	Texture *coffeeTexture;	  // Textura con los graficos de la palabra coffee
	Texture *crisisTexture;	  // Textura con los graficos de la plabra crisis
	Texture *gradientTexture; // Textura con los graficos para el degradado del fondo del titulo

	SDL_Rect backgroundWindow; // Ventana visible para la textura de fondo del titulo
	SDL_Texture *background;   // Textura dibujar el fondo del titulo

	AnimatedSprite *dustBitmapL; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
	AnimatedSprite *dustBitmapR; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo

	SmartSprite *coffeeBitmap; // Sprite con la palabra COFFEE para la pantalla de titulo
	SmartSprite *crisisBitmap; // Sprite con la palabra CRISIS para la pantalla de titulo

	Sprite *gradient; // Sprite para dibujar el degradado del titulo

	Text *text1; // Objeto de texto para poder escribir textos en pantalla
	Text *text2; // Objeto de texto para poder escribir textos en pantalla
	Fade *fade;	 // Objeto para realizar fundidos en pantalla

	// Variable
	JA_Music_t *titleMusic;						// Musica para el titulo
	JA_Sound_t *crashSound;						// Sonido con el impacto del título
	int backgroundCounter;						// Temporizador para el fondo de tiles de la pantalla de titulo
	int counter;								// Temporizador para la pantalla de titulo
	Uint32 ticks;								// Contador de ticks para ajustar la velocidad del programa
	Uint8 backgroundMode;						// Variable para almacenar el tipo de efecto que hará el fondo de la pantalla de titulo
	float sin[360];								// Vector con los valores del seno precalculados
	bool menuVisible;							// Indicador para saber si se muestra el menu del titulo o la frase intermitente
	bool demo;									// Indica si el modo demo estará activo
	section_t nextSection;						// Indica cual es la siguiente sección a cargar cuando termine el contador del titulo
	Uint32 ticksSpeed;							// Velocidad a la que se repiten los bucles del programa
	Uint8 postFade;								// Opción a realizar cuando termina el fundido
	menu_t menu;								// Variable con todos los objetos menus y sus variables
	struct options_t *options;					// Variable con todas las variables de las opciones del programa
	options_t optionsPrevious;					// Variable de respaldo para las opciones
	std::vector<input_t> availableInputDevices; // Vector con todos los metodos de control disponibles
	std::vector<int> deviceIndex;				// Indice para el jugador [i] del vector de dispositivos de entrada disponibles

	// Inicializa los valores
	void init();

	// Actualiza las variables del objeto
	void update();

	// Dibuja el objeto en pantalla
	void render();

	// Comprueba los eventos
	void checkEvents();

	// Comprueba las entradas
	void checkInput();

	// Actualiza el tileado de fondo
	void updateBG();

	// Cambia el valor de la variable de modo de pantalla completa
	void switchFullScreenModeVar();

	// Actualiza los elementos de los menus
	void updateMenuLabels();

	// Aplica las opciones de menu seleccionadas
	void applyOptions();

	// Ejecuta la parte donde se muestran las instrucciones
	void runInstructions(mode_e mode);

	// Ejecuta la parte donde se muestra la tabla de puntuaciones
	void runHiScoreTable(mode_hiScoreTable_e mode);

	// Ejecuta el juego en modo demo
	void runDemoGame();

	// Introduce el JailerID
	void runEnterID();

	// Modifica las opciones para los controles de los jugadores
	bool updatePlayerInputs(int numPlayer);

	// Crea el mosaico de fondo del titulo
	void createTiledBackground();

	// Comprueba cuantos mandos hay conectados para gestionar el menu de opciones
	void checkInputDevices();

	// Recarga las texturas
	void reLoadTextures();

	// Deshabilita ciertas opciones de los menus
	void disableMenuEntries();

public:
	// Constructor
	Title(SDL_Renderer *renderer, Screen *screen, Input *input, Asset *asset, options_t *options, Lang *lang, section_t *section);

	// Destructor
	~Title();

	// Bucle para el titulo del juego
	void run();
};

#endif
