#pragma once
#include "ifdefs.h"
#include "sprite.h"
#include "movingsprite.h"
#include "smartsprite.h"
#include "player.h"
#include "balloon.h"
#include "bullet.h"
#include "text.h"
#include "text2.h"
#include "menu.h"

#ifndef GAMEDIRECTOR_H
#define GAMEDIRECTOR_H

//GameDirector
class GameDirector
{
public:
	//Constructor
	GameDirector();

	//Destructor
	~GameDirector();

	//Iniciador
	void init(bool reset);

	//Arranca SDL y crea la ventana
	bool initSDL();

	//Carga todos los recursos
	bool loadMedia();

	//Libera todos los recursos y cierra SDL
	void close();

	//Establece el valor de la variable
	void setScore(Uint32 score);

	//Establece el valor de la variable
	void setHiScore(Uint32 score);

	//Actualiza el valor de HiScore en caso necesario
	void updateHiScore();

	//Transforma un valor numérico en una cadena de 6 cifras
	std::string updateScoreText(Uint32 num);

	//Pinta el marcador en pantalla usando un objeto texto
	void renderScoreBoard();

	//Mueve todos los globos activos
	void moveBalloons();

	//Pinta en pantalla todos los globos activos
	void renderBalloons();

	//Devuelve el primer indice no activo del vector de globos
	Uint8 getBallonFreeIndex();

	//Crea un globo nuevo en el vector de globos
	Uint8 createNewBalloon(float x, int y, Uint8 kind, float velx, Uint16 stoppedtimer, LTexture *texture);

	//Establece a cero todos los valores del vector de objetos globo
	void resetBalloons();

	//Explosiona un globo. Lo destruye y crea otros dos si es el caso
	void popBalloon(Uint8 index);

	//Detiene todos los globos
	void stopAllBalloons(Uint16 time);

	//Pone en marcha todos los globos
	void startAllBalloons();

	//Obtiene el numero de globos activos
	Uint8 countBalloons();

	//Comprueba la colisión entre el jugador y los globos activos
	bool checkPlayerBallonCollision();

	//Comprueba y procesa la colisión entre las balas y los globos
	void processBulletBallonCollision();

	//Mueve las balas activas
	void moveBullets();

	//Pinta las balas activas
	void renderBullets();

	//Devuelve el primer indice no activo del vector de balas
	Uint8 getBulletFreeIndex();

	//Establece a cero todos los valores del vector de objetos bala
	void resetBullets();

	//Crea un objeto bala
	void createBullet(int x, int y, Uint8 kind);

	//Acciones a realizar cuando el jugador muere
	void killPlayer();

	//Calcula y establece el valor de amenaza en funcion de los globos activos
	void calculateMenaceLevel();

	//Obtiene el valor de la variable
	Uint8 getMenaceLevel();

	//Obtiene el valor de la variable
	bool isPlayFieldDrawOnly();

	//Establece el valor de la variable
	void setPlayFieldDrawOnly(bool state);

	//Gestiona el nivel de amenaza
	void checkMenaceLevel();

	//Gestiona la entrada de teclado y mando durante el juego
	void checkGameInput();

	//Gestiona la entrada de teclado y mando durante el menu
	void checkMenuInput(Menu *menu);

	//Obtiene el valor de la variable
	Uint8 getGameStatus();

	//Establece el valor de la variable
	void setGameStatus(Uint8 status);

	//Pinta una transición en pantalla
	void renderTransition(Uint8 index);

	//Pinta el texto GetReady en pantalla
	void renderGetReady();

	//Agita la pantalla
	void shakeScreen();

	//Bucle para la intro del juego
	void runIntro();

	//Bucle para el titulo del juego
	void runTitle();

	//Bucle para el juego
	void runGame();

	//Bucle para el menu de pausa del juego
	void runPausedGame();

	//Bucle para la pantalla de game over
	void runGameOverScreen();

	//Dibuja la informacion de debug en pantalla
	void renderDebugInfo();

private:
	//La ventana donde dibujamos
	SDL_Window *mWindow;

	//El renderizador de la ventana
	SDL_Renderer *mRenderer;

	//Texturas con gráficos
	LTexture *mPlayerTexture;
	LTexture *mGameBackgroundTexture;
	LTexture *mTitleBackgroundTexture;
	LTexture *mWhiteFontTexture;
	LTexture *mNokiaFontTexture;
	LTexture *mMenuTexture;
	LTexture *mBalloonTexture;
	LTexture *mBulletTexture;
	LTexture *mMiscTexture;
	LTexture *mIntroTexture;

	//Manejador para el mando 1
	SDL_Joystick *gGameController;

	//Objetos con la música del juego
	Mix_Music *mTitleMusic;
	Mix_Music *mPlayingMusic;

	//Objetos con los efectos de sonido del juego
	Mix_Chunk *mPopBalloonFX;
	Mix_Chunk *mBulletFX;
	Mix_Chunk *mMenuSelectedFX;
	Mix_Chunk *mPlayerCollisionFX;
	Mix_Chunk *mHiScoreFX;

	//Datos del fichero
	Uint32 mDataFile[TOTAL_DATA];

	//Manejador de eventos
	SDL_Event *mEventHandler;

	//El jugador
	Player *mPlayer;

	//Vector con los objetos globo
	Balloon *mBalloon[MAX_BALLOONS];

	//Vector con los objetos bala
	Bullet *mBullet[MAX_BULLETS];

	//Fondo del juego
	Sprite *mGameBackground;

	//Fondo de la pantalla de titulo
	Sprite *mTitleBackground;

	//Texto blanco
	Text *mWhiteText;

	//Texto nuevo mejorado
	Text *mNewText;

	//Menu de la pantalla de título
	Menu *mMenuTitle;

	//Menú de la pantalla de pausa
	Menu *mMenuPause;

	//Notificación GetReady!
	SmartSprite *mGetReady;

	//Dibujos de la intro
	SmartSprite *mIntroBitmap[INTRO_TOTAL_BITMAPS];

	//Sprites con el titulo del juego para la pantalla de titulo
	SmartSprite *mCoffeeBitmap;
	SmartSprite *mCrisisBitmap;

	//Textos de la intro
	Text2 *mIntroText[INTRO_TOTAL_TEXTS];

	//Vector para coordinar los eventos de la intro
	Uint8 mIntroEvents[INTRO_TOTAL_EVENTS];

	//Indicador para el bucle principal
	Uint8 mGameStatus;

	//Puntuación actual y puntuación máxima
	Uint32 mScore;
	Uint32 mHiScore;

	//Indica si se ha superado la puntuación máxima
	bool mHiScoreAchieved;

	//Contador de ticks para ajustar la velocidad del juego
	Uint32 mOldTicks;

	//Velocidad a la que se repite el bucle de juego
	Uint8 mGameSpeed;

	//Nivel de amenaza actual
	Uint8 mMenaceLevel;

	//Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral,
	//se generan más globos. Si el umbral aumenta, aumenta el numero de globos
	Uint8 mMenaceLevelThreshold;

	//Indica si el bucle de juego avanza o solo pinta
	bool mPlayFieldDrawOnly;

	//Indica si se va a mostrar la información de debug
	bool mDebug;
};

#endif
