#pragma once

#include <SDL2/SDL.h>
#include "common/asset.h"
#include "common/debug.h"
#include "common/input.h"
#include "common/screen.h"
#include "common/text.h"
#include "common/utils.h"
#include "enemy_engine.h"
#include "item_tracker.h"
#include "map.h"
#include "player.h"
#include "scoreboard.h"

#ifndef GAME_H
#define GAME_H

class Game
{
private:
	SDL_Renderer *renderer;	  // El renderizador de la ventana
	Asset *asset;			  // Objeto encargado de gestionar los ficheros de recursos
	Screen *screen;			  // Objeto encargado de dibujar en pantalla
	Input *input;			  // Objeto Input para gestionar las entradas
	SDL_Event *eventHandler;  // Manejador de eventos
	JA_Music music;			  // Contiene la musica que se reproduce durante el juego
	Map *map;				  // Objeto encargado de gestionar el mapeado del juego
	Player *player;			  // Objeto para gestionar el jugador
	ItemTracker *itemTracker; // Objeto para gestionar los items recogidos
	EnemyEngine *enemyEngine; // Objeto encargado de gestionar los enemigos
	ScoreBoard *scoreboard;	  // Objeto encargado de gestionar el marcador
	board_t board;			  // Estructura con los datos del marcador
	Debug *debug;			  // Objeto para gestionar la información de debug
	SDL_Texture *spriteLayer; // Textura para dibujar los sprites
	section_t section;		  // Seccion actual dentro del programa
	Uint32 ticks;			  // Contador de ticks para ajustar la velocidad del programa
	Uint32 ticksSpeed;		  // Velocidad a la que se repiten los bucles del programa
	bool musicEnabled;		  // Indica si la musica puede sonar o no
	std::string currentMap;	  // Fichero del mapa actual
	player_t spawnPoint;	  // Lugar de la mapa donde aparece el jugador

	// Actualiza el juego, las variables, comprueba la entrada, etc.
	void update();

	// Pinta los objetos en pantalla
	void render();

	// Dibuja los sprites en la textura
	void fillSpriteTexture();

	// Copia la textura de sprites a la pantalla
	void renderSprites();

	// Comprueba los eventos de la cola
	void checkEventHandler();

	// Pone la información de debug en pantalla
	void updateDebugInfo();

	// Muestra información de depuración
	void renderDebugInfo();

	// Cambia el mapa
	bool changeMap(std::string file);

	// Comprueba si el jugador está en el borde y se ha de cambiar el mapa
	void checkScreenBorders();

	// Recarga las texturas
	void reLoadTextures();

	// Comprueba las colisiones del jugador con los enemigos
	bool checkPlayerEnemyCollisions();

	// Comprueba si el jugador esta vivo
	void checkIfPlayerIsAlive();

	// Mata al jugador
	void killPlayer();

public:
	// Constructor
	Game(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, Debug *debug);

	// Destructor
	~Game();

	// Bucle para el juego
	section_t run();
};

#endif
