/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/*
 * This code is based on the CRAB engine
 *
 * Copyright (c) Arvind Raja Yadav
 *
 * Licensed under MIT
 *
 */

#include "graphics/managed_surface.h"
#include "graphics/screen.h"
#include "crab/backInserter.h"
#include "crab/game.h"
#include "crab/LoadingScreen.h"
#include "crab/input/cursor.h"
#include "crab/rapidxml/rapidxml_print.hpp"

namespace Crab {

using namespace pyrodactyl::image;
using namespace pyrodactyl::ui;
using namespace pyrodactyl::input;

//------------------------------------------------------------------------
// Purpose: Loading stuff
//------------------------------------------------------------------------
void Game::startNewGame() {
	init(g_engine->_filePath->_modCur);
	loadLevel(_info.curLocID());
	_info.ironMan(g_engine->_tempData->_ironman);
	_savefile._ironman = g_engine->_tempData->_filename;
	_clock.start();
	_hud._pause.updateMode(_info.ironMan());

	createSaveGame(SAVEGAME_EVENT);
}

void Game::loadGame() {
	init(g_engine->_filePath->_modCur);
}

void Game::init(const Common::Path &filename) {
	g_engine->_loadingScreen->dim();
	g_engine->_eventStore->clear();
	_gameOver.clear(false);
	_state = STATE_GAME;
	_savefile._autoSlot = false;
	_gem.init();
	_info.Init();

	XMLDoc conf(filename);
	if (conf.ready()) {
		rapidxml::xml_node<char> *node = conf.doc()->first_node("config");

		_info.load(node);

		Common::Path path;
		if (nodeValid("level", node)) {
			loadPath(path, "list", node->first_node("level"));
			g_engine->_filePath->loadLevel(path);
		}

		if (nodeValid("hud", node)) {
			loadPath(path, "layout", node->first_node("hud"));
			_hud.load(path, _level._talkNotify, _level._destMarker);
		}

		if (nodeValid("sprite", node)) {
			loadPath(path, "animation", node->first_node("sprite"));
			_level.loadMoves(path);

			loadPath(path, "constant", node->first_node("sprite"));
			_level.loadConst(path);
		}

		if (nodeValid("event", node)) {
			_gem.load(node->first_node("event"), _popDefault);

			loadPath(path, "store", node->first_node("event"));
			g_engine->_eventStore->load(path);
		}

		if (nodeValid("map", node)) {
			loadPath(path, "layout", node->first_node("map"));
			_map.load(path, _info);
		}

		if (nodeValid("save", node))
			_savefile.load(node->first_node("save"));

		if (nodeValid("debug", node)) {
			loadPath(path, "layout", node->first_node("debug"));
			_debugConsole.load(path);
		}
	}

	_isInited = true;
}

bool Game::loadLevel(const Common::String &id, int playerX, int playerY) {
	if (g_engine->_filePath->_level.contains(id)) {
		g_engine->_loadingScreen->draw();

		// Load the assets local to this level
		// If the filename is same as the previous one, skip loading
		if (g_engine->_filePath->_currentR != g_engine->_filePath->_level[id]._asset) {
			g_engine->_filePath->_currentR = g_engine->_filePath->_level[id]._asset;
			g_engine->_imageManager->loadMap(g_engine->_filePath->_level[id]._asset);
		}

		// Load the level itself
		_level._pop = _popDefault;
		_level.load(g_engine->_filePath->_level[id]._layout, _info, _gameOver, playerX, playerY);

		// Set the current location
		_info.curLocID(id);
		_info.curLocName(g_engine->_filePath->_level[id]._name);
		_map._playerPos = _level._mapLoc;

		// Update and center the world map to the player current position
		_map.update(_info);
		_map.center(_map._playerPos);

		// If this is our first time visiting a level, reveal the associated area on the world map
		_map.revealAdd(_level._mapClip._id, _level._mapClip._rect);

		// Initialize inventory
		_info._inv.init(_level.playerId());

		// Initialize journal
		_info._journal.init(_level.playerId());

		_level.preDraw();
		return true;
	}

	return false;
}

//------------------------------------------------------------------------
// Purpose: Handle events
//------------------------------------------------------------------------
void Game::handleEvents(Common::Event &event, bool &shouldChangeState, GameStateID &newStateId) {
	g_engine->_mouse->handleEvents(event);

	//	if (GameDebug)
	//		debug_console.handleEvents(Event);

	if (!_debugConsole.restrictInput()) {
		if (_state == STATE_LOSE_MENU) {
			switch (_hud._gom.handleEvents(event)) {
			case 0:
				_state = STATE_LOSE_LOAD;
				break;
			case 1:
				quit(shouldChangeState, newStateId, GAMESTATE_MAIN_MENU);
				break;
			default:
				break;
			}
		} else if (_state == STATE_LOSE_LOAD) {
			if (g_engine->_loadMenu->handleEvents(event)) {
				shouldChangeState = true;
				newStateId = GAMESTATE_LOAD_GAME;
				return;
			}

			if (_hud._pausekey.handleEvents(event) || _hud._back.handleEvents(event) == BUAC_LCLICK)
				_state = STATE_LOSE_MENU;
		} else {
			if (!_gem.eventInProgress() && !_hud._pause.disableHotkeys()) {
				switch (_hud.handleEvents(_info, event)) {
				case HS_MAP:
					toggleState(STATE_MAP);
					break;
				case HS_PAUSE:
					g_engine->_thumbnail->copyFrom(g_engine->_screen->rawSurface());
					toggleState(STATE_PAUSE);
					break;
				case HS_CHAR:
					toggleState(STATE_CHARACTER);
					_gem._per.Cache(_info, _level.playerId(), _level);
					break;
				case HS_JOURNAL:
					toggleState(STATE_JOURNAL);
					break;
				case HS_INV:
					toggleState(STATE_INVENTORY);
					break;
				default:
					break;
				}
			}

			if (_state == STATE_GAME) {
				if (_gem.eventInProgress()) {
					_gem.handleEvents(_info, _level.playerId(), event, _hud, _level, _eventRes);
					if (applyResult())
						quit(shouldChangeState, newStateId, GAMESTATE_MAIN_MENU);
				} else {
					// Update the talk key state
					_info._talkKeyDown = g_engine->_inputManager->state(IG_TALK) || _level.containsClick(_info.lastPerson(), event);

					_level.handleEvents(_info, event);

					if (!_gameOver.empty() && _gameOver.evaluate(_info)) {
						_state = STATE_LOSE_MENU;
						_hud._gom.reset();
						return;
					}

#if 0
					if (g_engine->_inputManager->Equals(IG_QUICKSAVE, Event) == SDL_RELEASED) {
						CreateSaveGame(SAVEGAME_QUICK);
						return;
					} else if (g_engine->_inputManager->Equals(IG_QUICKLOAD, Event) == SDL_RELEASED && !info.IronMan()) {
						ShouldChangeState = true;
						NewStateID = GAMESTATE_LOAD_GAME;
						g_engine->_loadMenu->SelectedPath(FullPath(savefile.quick));
						return;
					}
#endif

					if (_hud._pausekey.handleEvents(event))
						toggleState(STATE_PAUSE);
				}
			} else if (_state == STATE_PAUSE) {
				switch (_hud._pause.handleEvents(event, _hud._back)) {
				case PS_RESUME:
					toggleState(STATE_GAME);
					_hud.setTooltip();
					break;

				case PS_SAVE:
					createSaveGame(SAVEGAME_NORMAL);
					toggleState(STATE_GAME);
					_hud.setTooltip();
					break;
				case PS_LOAD:
					//ShouldChangeState = true;
					//NewStateID = GAMESTATE_LOAD_GAME;
					return;

				case PS_HELP:
					toggleState(STATE_HELP);
					break;

				case PS_QUIT_MENU:
					createSaveGame(SAVEGAME_EXIT);
					quit(shouldChangeState, newStateId, GAMESTATE_MAIN_MENU);
					break;

				case PS_QUIT_GAME:
					createSaveGame(SAVEGAME_EXIT);
					quit(shouldChangeState, newStateId, GAMESTATE_EXIT);
					break;
				default:
					break;
				}
			} else {
				if (_hud._back.handleEvents(event) == BUAC_LCLICK)
					toggleState(STATE_GAME);

				switch (_state) {
				case STATE_MAP:
					if (_map.handleEvents(_info, event)) {
						// We need to load the new level
						loadLevel(_map._curLoc);
						toggleState(STATE_GAME);
					}
					break;
				case STATE_JOURNAL:
					if (_info._journal.handleEvents(_level.playerId(), event)) {
						// This means we selected the "find on map" button, so we need to:
						// switch to the world map, and highlight the appropriate quest marker
						_map.selectDest(_info._journal._markerTitle);
						toggleState(STATE_MAP);
					}
					break;
				case STATE_CHARACTER:
					_gem._per.handleEvents(_info, _level.playerId(), event);
					break;
				case STATE_INVENTORY:
					_info._inv.handleEvents(_level.playerId(), event);
					break;
				case STATE_HELP:
					g_engine->_helpScreen->handleEvents(event);
				default:
					break;
				}
			}
		}
	}
}

#if 0
//------------------------------------------------------------------------
// Purpose: Handle events
//------------------------------------------------------------------------
void Game::handleEvents(SDL_Event &Event, bool &ShouldChangeState, GameStateID &NewStateID) {
	g_engine->_mouse->handleEvents(Event);

	if (GameDebug)
		debug_console.handleEvents(Event);

	if (!debug_console.RestrictInput()) {
		if (state == STATE_LOSE_MENU) {
			switch (hud.gom.handleEvents(Event)) {
			case 0:
				state = STATE_LOSE_LOAD;
				break;
			case 1:
				Quit(ShouldChangeState, NewStateID, GAMESTATE_MAIN_MENU);
				break;
			default:
				break;
			}
		} else if (state == STATE_LOSE_LOAD) {
			if (g_engine->_loadMenu->handleEvents(Event)) {
				ShouldChangeState = true;
				NewStateID = GAMESTATE_LOAD_GAME;
				return;
			}

			if (hud.pausekey.handleEvents(Event) || hud.back.handleEvents(Event) == BUAC_LCLICK)
				state = STATE_LOSE_MENU;
		} else {
			if (!gem.EventInProgress() && !hud.pause.DisableHotkeys()) {
				switch (hud.handleEvents(info, Event)) {
				case HS_MAP:
					ToggleState(STATE_MAP);
					break;
				case HS_PAUSE:
					ToggleState(STATE_PAUSE);
					break;
				case HS_CHAR:
					ToggleState(STATE_CHARACTER);
					gem.per.Cache(info, level.PlayerID(), level);
					break;
				case HS_JOURNAL:
					ToggleState(STATE_JOURNAL);
					break;
				case HS_INV:
					ToggleState(STATE_INVENTORY);
					break;
				default:
					break;
				}
			}

			if (state == STATE_GAME) {
				if (gem.EventInProgress()) {
					gem.handleEvents(info, level.PlayerID(), Event, hud, level, event_res);
					if (ApplyResult())
						Quit(ShouldChangeState, NewStateID, GAMESTATE_MAIN_MENU);
				} else {
					// Update the talk key state
					info.TalkKeyDown = g_engine->_inputManager->State(IG_TALK) || level.ContainsClick(info.LastPerson(), Event);

					level.handleEvents(info, Event);

					if (!game_over.Empty() && game_over.Evaluate(info)) {
						state = STATE_LOSE_MENU;
						hud.gom.reset();
						return;
					}

					if (g_engine->_inputManager->Equals(IG_QUICKSAVE, Event) == SDL_RELEASED) {
						CreateSaveGame(SAVEGAME_QUICK);
						return;
					} else if (g_engine->_inputManager->Equals(IG_QUICKLOAD, Event) == SDL_RELEASED && !info.IronMan()) {
						ShouldChangeState = true;
						NewStateID = GAMESTATE_LOAD_GAME;
						g_engine->_loadMenu->SelectedPath(FullPath(savefile.quick));
						return;
					}

					if (hud.pausekey.handleEvents(Event))
						ToggleState(STATE_PAUSE);
				}
			} else if (state == STATE_PAUSE) {
				switch (hud.pause.handleEvents(Event, hud.back)) {
				case PS_RESUME:
					ToggleState(STATE_GAME);
					hud.SetTooltip();
					break;

				case PS_SAVE:
					CreateSaveGame(SAVEGAME_NORMAL);
					ToggleState(STATE_GAME);
					hud.SetTooltip();
					break;
				case PS_LOAD:
					ShouldChangeState = true;
					NewStateID = GAMESTATE_LOAD_GAME;
					return;

				case PS_HELP:
					ToggleState(STATE_HELP);
					break;

				case PS_QUIT_MENU:
					CreateSaveGame(SAVEGAME_EXIT);
					Quit(ShouldChangeState, NewStateID, GAMESTATE_MAIN_MENU);
					break;

				case PS_QUIT_GAME:
					CreateSaveGame(SAVEGAME_EXIT);
					Quit(ShouldChangeState, NewStateID, GAMESTATE_EXIT);
					break;
				default:
					break;
				}
			} else {
				if (hud.back.handleEvents(Event) == BUAC_LCLICK)
					ToggleState(STATE_GAME);

				switch (state) {
				case STATE_MAP:
					if (map.handleEvents(info, Event)) {
						// We need to load the new level
						LoadLevel(map.cur_loc);
						ToggleState(STATE_GAME);
					}
					break;
				case STATE_JOURNAL:
					if (info.journal.handleEvents(level.PlayerID(), Event)) {
						// This means we selected the "find on map" button, so we need to:
						// switch to the world map, and highlight the appropriate quest marker
						map.SelectDest(info.journal.marker_title);
						ToggleState(STATE_MAP);
					}
					break;
				case STATE_CHARACTER:
					gem.per.handleEvents(info, level.PlayerID(), Event);
					break;
				case STATE_INVENTORY:
					info.inv.handleEvents(level.PlayerID(), Event);
					break;
				case STATE_HELP:
					g_engine->_helpScreen->handleEvents(Event);
				default:
					break;
				}
			}
		}
	}
}
#endif

//------------------------------------------------------------------------
// Purpose: InternalEvents
//------------------------------------------------------------------------
void Game::internalEvents(bool &shouldChangeState, GameStateID &newStateId) {
	switch (_state) {
	case STATE_GAME:
		_hud.internalEvents(_level.showMap());
		_eventRes.clear();

		{
			// HACK: Since sequences can only be ended in GameEventManager, we use this empty array
			// to get effects to work for levels
			Common::Array<pyrodactyl::event::EventSeqInfo> endSeq;
			applyResult(_level.internalEvents(_info, _eventRes, endSeq, _gem.eventInProgress()));
		}

		_gem.internalEvents(_info, _level, _eventRes);
		_info._talkKeyDown = false;

		if (applyResult())
			quit(shouldChangeState, newStateId, GAMESTATE_MAIN_MENU);

		break;
	case STATE_MAP:
		_map.internalEvents(_info);
		break;
	case STATE_CHARACTER:
		_gem._per.internalEvents();
		break;
	default:
		break;
	}
}
//------------------------------------------------------------------------
// Purpose: Draw
//------------------------------------------------------------------------
void Game::draw() {
	if (_gem._drawGame)
		_level.draw(_info);
	else
		g_engine->_imageManager->blackScreen();
	switch (_state) {
	case STATE_GAME:
		if (_gem.eventInProgress())
			_gem.draw(_info, _hud, _level);
		else
			_hud.draw(_info, _level.playerId());
		break;
	case STATE_PAUSE:
		g_engine->_imageManager->dimScreen();
		_hud._pause.draw(_hud._back);
		_hud.draw(_info, _level.playerId());
		break;
	case STATE_MAP:
		g_engine->_imageManager->dimScreen();
		_map.draw(_info);
		_hud.draw(_info, _level.playerId());
		_hud._back.draw();
		break;
	case STATE_JOURNAL:
		g_engine->_imageManager->dimScreen();
		_info._journal.draw(_level.playerId());
		_hud.draw(_info, _level.playerId());
		_hud._back.draw();
		break;
	case STATE_CHARACTER:
		g_engine->_imageManager->dimScreen();
		_gem._per.draw(_info, _level.playerId());
		_hud.draw(_info, _level.playerId());
		_hud._back.draw();
		break;
	case STATE_INVENTORY:
		g_engine->_imageManager->dimScreen();
		_info.invDraw(_level.playerId());
		_hud.draw(_info, _level.playerId());
		_hud._back.draw();
		break;
	case STATE_HELP:
		g_engine->_imageManager->dimScreen();
		g_engine->_helpScreen->draw();
		_hud._back.draw();
		_hud.draw(_info, _level.playerId());
		break;
	case STATE_LOSE_MENU:
		_hud._gom.draw();
		break;
	case STATE_LOSE_LOAD:
		g_engine->_loadMenu->draw();
		_hud._back.draw();
		break;
	default:
		break;
	}

	if (GameDebug)
		_debugConsole.draw(_info);
	g_engine->_mouse->draw();
}

//------------------------------------------------------------------------
// Purpose: Apply results of events and levels
//------------------------------------------------------------------------
bool Game::applyResult() {
	using namespace pyrodactyl::event;

	for (const auto &i : _eventRes) {
		switch (i._type) {
		case ER_MAP:
			if (i._val == "img")
				_map.setImage(i._y);
			else if (i._val == "pos") {
				_map._playerPos.x = i._x;
				_map._playerPos.y = i._y;
			}
			break;
		case ER_DEST:
			if (i._x < 0 || i._y < 0) {
				_info._journal.marker(_level.playerId(), i._val, false);
				_map.destDel(i._val);
			} else {
				_map.destAdd(i._val, i._x, i._y);
				_info._journal.marker(_level.playerId(), i._val, true);
				_info._unread._map = true;
			}
			break;
		case ER_IMG:
			playerImg();
			break;
		case ER_TRAIT:
			if (i._x == 42)
				_info.traitDel(i._val, i._y);
			else
				_info.traitAdd(i._val, i._y);
			break;
		case ER_LEVEL:
			if (i._val == "Map")
				toggleState(STATE_MAP);
			else
				loadLevel(i._val, i._x, i._y);
			break;
		case ER_MOVE:
			for (auto &o : _level._objects) {
				if (i._val == o.id()) {
					o.x(i._x);
					o.y(i._y);
					break;
				}
			}
			break;
		case ER_PLAYER:
			// First stop the movement of the current player sprite
			_level.playerStop();

			// Then swap to the new id
			_level.playerId(i._val, i._x, i._y);

			// Stop the new player sprite's movement as well
			_level.playerStop();
			break;
		case ER_SAVE:
			createSaveGame(SAVEGAME_EVENT);
			break;
		case ER_SYNC:
			_level.calcProperties(_info);
			_map.update(_info);
			break;
		case ER_QUIT:
			g_engine->_tempData->_credits = (i._val == "credits");
			return true;
		default:
			break;
		}
	}

	_gem._per.Cache(_info, _level.playerId(), _level);
	_eventRes.clear();
	return false;
}

void Game::applyResult(LevelResult result) {
	switch (result._type) {
	case LR_LEVEL:
		if (result._val == "Map")
			toggleState(STATE_MAP);
		else
			loadLevel(result._val, result._x, result._y);
		return;
	case LR_GAMEOVER:
		_state = STATE_LOSE_MENU;
		_hud._gom.reset();
		break;
	default:
		break;
	}
}

//------------------------------------------------------------------------
// Purpose: Save/load game
//------------------------------------------------------------------------
bool Game::loadState(Common::SeekableReadStream *stream) {
	Common::String data = stream->readString();
	uint64 end = data.findLastOf(">");
	if (end == Common::String::npos) // invalid save file, returning false from here will display "Reading data failed" dialogbox
		return false;

	// +1 to include > as well
	end++;

	uint8 *dataC = new uint8[end + 1];
	dataC[end] = '\0';
	memcpy(dataC, data.c_str(), end);
	XMLDoc conf(dataC);

	if (!_isInited)
		loadGame();

	if (conf.ready()) {
		rapidxml::xml_node<char> *node = conf.doc()->first_node("save");
		if (nodeValid(node)) {
			_info.loadIronMan(node);
			loadStr(_savefile._ironman, "file", node);
			_hud._pause.updateMode(_info.ironMan());

			if (nodeValid("events", node))
				_gem.loadState(node->first_node("events"));

			if (nodeValid("info", node))
				_info.loadState(node->first_node("info"));

			if (nodeValid("map", node))
				_map.loadState(node->first_node("map"));

			playerImg();

			Common::String loc;
			loadStr(loc, "loc_id", node);
			loadLevel(loc);

			if (nodeValid("level", node))
				_level.loadState(node->first_node("level"));

			_gem._per.Cache(_info, _level.playerId(), _level);

			Common::String playtime;
			loadStr(playtime, "time", node);
			_clock.start(playtime);
		}
	}

	return true;
}
//------------------------------------------------------------------------
// Purpose: Write game state to file
//------------------------------------------------------------------------
void Game::saveState(Common::SeekableWriteStream *stream) {
	rapidxml::xml_document<char> doc;

	// xml declaration
	rapidxml::xml_node<char> *decl = doc.allocate_node(rapidxml::node_declaration);
	decl->append_attribute(doc.allocate_attribute("version", "1.0"));
	decl->append_attribute(doc.allocate_attribute("encoding", "utf-8"));
	doc.append_node(decl);

	// root node
	rapidxml::xml_node<char> *root = doc.allocate_node(rapidxml::node_element, "save");
	doc.append_node(root);

	// Save location id
	Common::String loc = _info.curLocID();
	root->append_attribute(doc.allocate_attribute("loc_id", loc.c_str()));

	// Save location name
	Common::String locName = _info.curLocName();
	root->append_attribute(doc.allocate_attribute("loc_name", locName.c_str()));

	// Save player character name
	Common::String charName;
	if (_info.personValid(_level.playerId()))
		charName = _info.personGet(_level.playerId())._name;
	root->append_attribute(doc.allocate_attribute("char_name", charName.c_str()));

	// Difficulty
	Common::String diff = "Normal";
	if (_info.ironMan())
		diff = "Iron Man";
	root->append_attribute(doc.allocate_attribute("diff", diff.c_str()));

	// Save file used if iron man
	root->append_attribute(doc.allocate_attribute("file", _savefile._ironman.c_str()));

	// Preview image used
	root->append_attribute(doc.allocate_attribute("preview", _level._previewPath.toString('/').c_str()));

	// Time played
	Common::String playtime = _clock.getTime();
	root->append_attribute(doc.allocate_attribute("time", playtime.c_str()));

	rapidxml::xml_node<char> *childGem = doc.allocate_node(rapidxml::node_element, "events");
	_gem.saveState(doc, childGem);
	root->append_node(childGem);

	rapidxml::xml_node<char> *childInfo = doc.allocate_node(rapidxml::node_element, "info");
	_info.saveState(doc, childInfo);
	root->append_node(childInfo);

	rapidxml::xml_node<char> *childMap = doc.allocate_node(rapidxml::node_element, "map");
	_map.saveState(doc, childMap);
	root->append_node(childMap);

	rapidxml::xml_node<char> *childLevel = doc.allocate_node(rapidxml::node_element, "level");
	_level.saveState(doc, childLevel);
	root->append_node(childLevel);

	Common::String xmlAsString;
	rapidxml::print(Crab::backInserter(xmlAsString), doc);

	stream->writeString(xmlAsString);
}
//------------------------------------------------------------------------
// Purpose: Quit the game
//------------------------------------------------------------------------
void Game::quit(bool &shouldChangeState, GameStateID &newStateId, const GameStateID &newStateVal) {
	shouldChangeState = true;
	newStateId = newStateVal;
	g_engine->_imageManager->loadMap(g_engine->_filePath->_mainmenuR);
}
//------------------------------------------------------------------------
// Purpose: Change our internal state
//------------------------------------------------------------------------
void Game::toggleState(const State &s) {
	if (_state != s)
		_state = s;
	else
		_state = STATE_GAME;

	// If we are in game state switch to KBM_GAME
	if (_state == STATE_GAME && g_engine->_inputManager->getKeyBindingMode() != KBM_GAME) {
		g_engine->_inputManager->setKeyBindingMode(KBM_GAME);
	}

	// This is because game is the first state, the rest are in order
	_hud.State(_state - 1);
	_hud._pause.reset();

	// Only load help screen image if we have to
	if (_state == STATE_HELP)
		g_engine->_helpScreen->refresh();
	else
		g_engine->_helpScreen->clear();
}

//------------------------------------------------------------------------
// Purpose: Use this function to actually save your games
//------------------------------------------------------------------------
void Game::createSaveGame(const SaveGameType &savetype) {
#if 0
	// Disregard type in iron man mode, we only save to one file
	if (info.IronMan())
		saveState(savefile.ironman, true);
	else {
		switch (savetype) {
		case SAVEGAME_NORMAL:
			saveState(hud.pause.SaveFile(), false);
			break;

		case SAVEGAME_EVENT:
			if (savefile.auto_slot)
				saveState(savefile.auto_2, true);
			else
				saveState(savefile.auto_1, true);

			savefile.auto_slot = !savefile.auto_slot;
			break;

		case SAVEGAME_EXIT:
			saveState(savefile.auto_quit, true);
			break;
		case SAVEGAME_QUICK:
			saveState(savefile.quick, true);
			break;
		default:
			break;
		}
	}
#endif
}

void Game::setUI() {
	_map.setUI();
	_hud.setUI();

	g_engine->_loadMenu->setUI();
	g_engine->_optionMenu->setUI();

	_gem.setUI();
	_info.setUI();
	_level.setUI();
}

} // End of namespace Crab
