/**
 * @file Game.h
 * 
 * High-level controller of the game logic.
 */

#ifndef _H_GAME
#define _H_GAME

#include <stdbool.h>

#include "Bitmap.h"
#include "Entity.h"
#include "ExMath.h"
#include "Inventory.h"
#include "rovdefs.h"
#include "Player.h"
#include "RPK.h"

#define GAME_TICKS_PER_SECOND 30

enum InputType
{
	INPUT_KEY_NULL,
	INPUT_KEY_FORWARD,
	INPUT_KEY_BACKWARD,
	INPUT_KEY_STRAFELEFT,
	INPUT_KEY_STRAFERIGHT,
	INPUT_KEY_TURNLEFT,
	INPUT_KEY_TURNRIGHT,
	INPUT_KEY_ATTACK,
	INPUT_KEY_USE,
	INPUT_KEY_MAP,
	INPUT_KEY_DROP,
	INPUT_KEY_INVENTORY,
	INPUT_KEY_PAUSE,
	INPUT_KEY_HOTBARPREV,
	INPUT_KEY_HOTBARNEXT,
	INPUT_KEY_HOTBAR1,
	INPUT_KEY_HOTBAR2,
	INPUT_KEY_HOTBAR3,
	INPUT_KEY_HOTBAR4,
	INPUT_KEY_HOTBAR5,
	INPUT_KEY_CONSOLE,
	INPUT_KEY_MENUUP,
	INPUT_KEY_MENUDOWN,
	INPUT_KEY_MENULEFT,
	INPUT_KEY_MENURIGHT,
	INPUT_KEY_MENUACCEPT,
	INPUT_KEY_MENUCLOSE,
	NUM_INPUTS
};
#define INPUTMODE_KEYBOARDMOUSE 0
#define INPUTMODE_KEYBOARDONLY 1
#define INPUTMODE_CONTROLLER 2

#define GAME_CHEAT_NOCLIP 1
#define GAME_CHEAT_GODMODE 2

struct Options
{
	int width, height;
	int fullscreen;
	float mouseSens;
	float masterVolume, sfxVolume, musicVolume;
};

struct GuiMenu;

extern struct _GameState
{
	enum { GAME_STATE_PLAY, GAME_STATE_PAUSED, GAME_STATE_DEAD, GAME_STATE_XLEVEL, GAME_STATE_TITLE } state;
	int depth;
	bool inventoryOpen, mapOpen;
	struct Options options;
	int globalReg[4];
	time levelTime;
	struct
	{
		bool keys[NUM_INPUTS];
		struct InputCmd command;
		int mode;
	} input;
	struct GuiMenu *activeMenu;
	int consoleOpen;
	int respawnTimer; // Respawn timer for the local player when in multiplayer mode
	int cheats;
	char serverAddr[64];
} Game;

void Game_SaveAllIfNeeded(void);

void Game_Init(RPKFile *);
void Game_Cleanup(void);

#define GAME_START_FLOOR 1

enum GameStartType
{
	// Removes the old save file, and starts a new game from the beginning.
	GAME_START_NEW,
	// Loads the exising save file and continues the game.
	GAME_START_CONTINUE,
	// Begins a new game and starts a multiplayer server
	GAME_START_HOST,
	// Joins a remote multiplayer server
	GAME_START_JOIN,
};

void Game_Start(enum GameStartType type, int floor);
/* Warps to position at specified floor, or a random position if the coordinates are less than 0. */
void Game_ChangeFloor(int, float, float);
void Game_TogglePaused(void);
void Game_QuitToTitle(void);

void Game_SaveOptions(void);
struct Options *Game_LoadOptions(void);

struct GuiMenu;

void Game_SetMenu(struct GuiMenu *);

/* Called at a fixed rate based on GAME_TICKS_PER_SECOND */
void Game_Tick(void);
/* Called every frame, used for updating physics and motion */
void Game_Update(float deltaTime);
void Game_Render(Bmp_t *, float delta);

void Game_ShowStatusMsg(const char *msg);

void Game_OnKey(enum InputType, int pressed);
bool Game_OnMouseClick(int x, int y);
void Game_OnMouseMove(int x, int y, float delta);
void Game_OnScroll(int direction);

#endif
