/*
  File name: CCytadelaMenu.cpp
  Copyright: (C) 2004 - 2013 Tomasz Kazmierczak

  This file is part of Cytadela
  (an example of how NOT to design in-game menu)

 *   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/>.  *

*/

#include "CCytadelaMenu.h"
#include <memory.h>
#include <cassert>

CCytadelaMenu::CCytadelaMenu() :
	mSDL(CSDLClass::instance()),
	mConfig(CCytadelaConfig::instance()),
	mLocalization(Localization::instance())
{
	//menu texts and text positions
	//MAIN MENU
	const char *text = mLocalization->getText(LOC_MENU_START);
	sprintf(mMenuTexts[MENU_MAIN][0], "%s", text);
	mMenuTextsXOffs[MENU_MAIN][0] = 120 - (strlen(text) * 8);

	text = mLocalization->getText(LOC_MENU_LOAD);
	sprintf(mMenuTexts[MENU_MAIN][1], "%s", text);
	mMenuTextsXOffs[MENU_MAIN][1] = 120 - (strlen(text) * 8);

	text = mLocalization->getText(LOC_MENU_OPTIONS);
	sprintf(mMenuTexts[MENU_MAIN][2], "%s", text);
	mMenuTextsXOffs[MENU_MAIN][2] = 120 - (strlen(text) * 8);

	text = mLocalization->getText(LOC_MENU_TRAINING);
	sprintf(mMenuTexts[MENU_MAIN][3], "%s", text);
	mMenuTextsXOffs[MENU_MAIN][3] = 120 - (strlen(text) * 8);

	mMenuTexts[MENU_MAIN][4][0] = 0;
	mMenuTextsXOffs[MENU_MAIN][4] = 0;

	text = mLocalization->getText(LOC_MENU_INFO);
	sprintf(mMenuTexts[MENU_MAIN][5], "%s", text);
	mMenuTextsXOffs[MENU_MAIN][5] = 120 - (strlen(text) * 8);

	//LOAD MENU
	for(int32_t i = 0; i < 5 ; ++i) {
		//offsets for save names (-8)
		mMenuTextsXOffs[MENU_LOAD][i] = -8;
		mMenuTexts[MENU_LOAD][i][0] = 0;
	}
	text = mLocalization->getText(LOC_MENU_MENU);
	sprintf(mMenuTexts[MENU_LOAD][5], "%s", text);
	mMenuTextsXOffs[MENU_LOAD][5] = 120 - (strlen(text) * 8);

	//OPTIONS menu
	mMenuTextsXOffs[MENU_SETTINGS][0] = 0;
	mMenuTexts[MENU_SETTINGS][0][0] = 0;

	text = mLocalization->getText(LOC_MENU_VIDEO_OPTIONS);
	sprintf(mMenuTexts[MENU_SETTINGS][1], "%s", text);
	mMenuTextsXOffs[MENU_SETTINGS][1] = 120 - (strlen(text) * 8);

	text = mLocalization->getText(LOC_MENU_SPEED_SETTINGS);
	sprintf(mMenuTexts[MENU_SETTINGS][2], "%s", text);
	mMenuTextsXOffs[MENU_SETTINGS][2] = 120 - (strlen(text) * 8);

	text = mLocalization->getText(LOC_MENU_AUDIO_SETTINGS);
	sprintf(mMenuTexts[MENU_SETTINGS][3], "%s", text);
	mMenuTextsXOffs[MENU_SETTINGS][3] = 120 - (strlen(text) * 8);

	mMenuTextsXOffs[MENU_SETTINGS][4] = 0;
	mMenuTexts[MENU_SETTINGS][4][0] = 0;

	text = mLocalization->getText(LOC_MENU_MENU);
	sprintf(mMenuTexts[MENU_SETTINGS][5], "%s", text);
	mMenuTextsXOffs[MENU_SETTINGS][5] = 120 - (strlen(text) * 8);

	//TRAINING MENU
	text = mLocalization->getText(LOC_MENU_TRAINING_1);
	sprintf(mMenuTexts[MENU_TRAINING][0], "%s", text);
	mMenuTextsXOffs[MENU_TRAINING][0] = 120 - (strlen(text) * 8);

	text = mLocalization->getText(LOC_MENU_TRAINING_2);
	sprintf(mMenuTexts[MENU_TRAINING][1], "%s", text);
	mMenuTextsXOffs[MENU_TRAINING][1] = 120 - (strlen(text) * 8);

	text = mLocalization->getText(LOC_MENU_TRAINING_3);
	sprintf(mMenuTexts[MENU_TRAINING][2], "%s", text);
	mMenuTextsXOffs[MENU_TRAINING][2] = 120 - (strlen(text) * 8);

	text = mLocalization->getText(LOC_MENU_TRAINING_4);
	sprintf(mMenuTexts[MENU_TRAINING][3], "%s", text);
	mMenuTextsXOffs[MENU_TRAINING][3] = 120 - (strlen(text) * 8);

	text = mLocalization->getText(LOC_MENU_TRAINING_5);
	sprintf(mMenuTexts[MENU_TRAINING][4], "%s", text);
	mMenuTextsXOffs[MENU_TRAINING][4] = 120 - (strlen(text) * 8);

	text = mLocalization->getText(LOC_MENU_MENU);
	sprintf(mMenuTexts[MENU_TRAINING][5], "%s", text);
	mMenuTextsXOffs[MENU_TRAINING][5] = 120 - (strlen(text) * 8);

	//GFX OPTIONS menu
	for(int32_t i = 0; i < 5 ; ++i) {
		mMenuTextsXOffs[MENU_VIDEO][i] = 0;
		mMenuTexts[MENU_VIDEO][i][0] = 0;
	}
	text = mLocalization->getText(LOC_MENU_MENU);
	sprintf(mMenuTexts[MENU_VIDEO][5], "%s", text);
	mMenuTextsXOffs[MENU_VIDEO][5] = 120 - (strlen(text) * 8);

	//GAME SPEED menu
	for(int32_t i = 0; i < 5 ; ++i) {
		mMenuTextsXOffs[MENU_GAME_SPEED][i] = 0;
		mMenuTexts[MENU_GAME_SPEED][i][0] = 0;
	}
	text = mLocalization->getText(LOC_MENU_MENU);
	sprintf(mMenuTexts[MENU_GAME_SPEED][5], "%s", text);
	mMenuTextsXOffs[MENU_GAME_SPEED][5] = 120 - (strlen(text) * 8);

	//AUDIO SETTINGS menu
	for(int32_t i = 0; i < 5 ; ++i) {
		mMenuTextsXOffs[MENU_AUDIO][i] = 0;
		mMenuTexts[MENU_AUDIO][i][0] = 0;
	}
	text = mLocalization->getText(LOC_MENU_MENU);
	sprintf(mMenuTexts[MENU_AUDIO][5], "%s", text);
	mMenuTextsXOffs[MENU_AUDIO][5] = 120 - (strlen(text) * 8);

	//set the info texts
	static const char *defaultLang =
"                               ...CYTADELA...\n"
"                                 WERSJA 1.1.0\n"
"                 COPYRIGHT (C) 2003-2013 TOMASZ KAxMIERCZAK\n"
"                     COPYRIGHT (C) 2006 KAMIL PAWlOWSKI\n"
"                     COPYRIGHT (C) 2009 MARCIN SeKALSKI\n"
"                    COPYRIGHT (C) 2009 TOMASZ WIsNIEWSKI\n\n"
"CYTADELA JEST ROZPOWSZECHNIANA NA WARUNKACH OGoLNEJ LICENCJJI PUBLICZNEJ GNU\n"
"(GNU GENERAL PUBLIC LICENSE, GNU GPL) - WEDlUG WERSJI 3-CIEJ TEJ LICENCJI, LUB\n"
"(JEsLI WOLISZ) KToREJKOLWIEK Z PoxNIEJSZYCH WERSJI.\n"
"CYTADELA NIE JEST OBJeTA JAKaKOLWIEK GWARANCJa. PRZECZYTAJ PLIK \"COPYING\"\n"
"(TREsc LICENCJI GNU GPL) BY DOWIEDZIEc SIe WIeCEJ. PLIK ZNAJDUJE SIe W KATALOGU\n"
"Z DOKUMENTACJa GRY.\n\n"
"CYTADELA JEST KONWERSJa AMIGOWEJ GRY O TYM SAMYM TYTULE, STWORZONEJ PRZEZ\n"
"GRUPe VIRTUAL DESIGN. W KONWERSJI WYKORZYSTANYCH JEST KILKA ALGORYTMoW\n"
"POCHODZaCYCH Z ORYGINAlU. CAlA MUZYKA, WIeKSZOsc GRAFIKI, WSZYSTKIE DxWIeKI I\n"
"POZIOMY POCHODZa Z WERSJI ORYGINALNEJ, ALE W NIEKToRYCH PRZYPADKACH ZOSTAlY\n"
"PRZETWORZONE I/LUB ZMODYFIKOWANE W CELU UlATWIENIA WYKORZYSTANIA ICH W\n"
"KONWERSJI I POPRAWIENIA KILKU BleDoW.\n\n"
"WSZYSTKIE ELEMENTY POCHODZaCE Z ORYGINAlU, O KToRYCH MOWA POWYzEJ, ZOSTAlY\n"
"ZAPOzYCZONE Z ORYGINAlU ZA ZGODa ICH AUTORoW. ICH ROZPOWSZECHNIANIE (JAKO CZesCI\n"
"KONWERSJI) JEST DOZWOLONE NA ZASADACH OKREsLONYCH PRZEZ GNU GPL.\n\n\n"
"                          SWoJ WKlAD DO PROJEKTU DALI:\n"
"                        (W KOLEJNOscI DODAWANIA DO LISTY)\n"
"                        ---------------------------------\n"
"TOMASZ KAxMIERCZAK\n"
"   -PROGRAMOWANIE\n"
"   -NIEKToRE ELEMENTY GRAFIKI 2D\n"
"   -PRZYSTOSOWANIE ORYGINALNEJ GRAFIKI 2D/3D DO ENGINE'U CYTADELI\n"
"   -DOKUMENTACJA DO GRY (OPARTA NA DOKUMENTACJI ORYGINALNEJ)\n"
"   -POLSKIE, ANGIELSKIE I NIEMIECKIE TlUMACZENIA (OPARTE NA TlUMACZENIACH\n"
"    ORYGINALNYCH)\n\n"
"KAMIL PAWlOWSKI\n"
"   -UTWORZENIE SKRYPToW \"CONFIGURE\" I \"MAKE\" I ZWIaZANE Z NIMI MODYFIKACJE\n"
"    W KODZIE\n\n"
"KRZYSZTOF SMULKOWSKI\n"
"   -DUzO TESTOWANIA I ZNALEZIONYCH BleDoW. WIELKIE DZIeKI!\n\n"
"JOSEF KOROUS\n"
"   -TESTOWANIE\n"
"   -TlUMACZENIE CZESKIE\n\n"
"MARCIN SeKALSKI\n"
"   -EKRANY INFORMACYJNE PRZED POZIOMAMI TRENINGOWYMI\n"
"   -ALFA I BETA TESTY\n"
"   -DUzO ZNALEZIONYCH BLEDoW\n"
"   -UzYTECZNE SUGESTIE DOTYCZaCE GRY\n\n"
"KRYSTIAN WlOSEK\n"
"   -UTWORZENIE PAKIEToW DLA DEBIANA\n\n"
"PATRICK DAVID\n"
"   -TlUMACZENIE FRANCUSKIE GRY I DOKUMENTACJI\n\n"
"TOMASZ WIsNIEWSKI\n"
"   -POMOC W PRZYSTOSOWANIU DO PROCESORoW BIG-ENDIANOWYCH\n"
"   -UTWORZENIE PAKIEToW DLA MACOS X\n\n"
"RAFAl STEFANOWSKI\n"
"   -BETA TESTY\n\n"
"\n\n"
"                         AUTORZY WERSJI ORYGINALNEJ:\n"
"                         ---------------------------\n"
"                         PAWEl MATUSZ - POMYSl I PROGRAMOWANIE\n"
"                      ARTUR BARDOWSKI - GRAFIKA I ANIMACJE\n"
"                   RADOSlAW CZECZOTKA - GRAFIKA DO POZIOMoW\n"
"                          ARTUR OPALA - MUZYKA I EFEKTY DZWIeKOWE\n"
"\n"
"               DO POWSTANIA WERSJI ORYGINALNEJ PRZYCZYNIlO SIe\n"
"                 TAKzE WIELE INNYCH, NIEWYMIENIONYCH TU OSoB\n"
"\n";

	static const char *otherLang =
"                               ...CYTADELA...\n"
"                                 VERSION 1.1.0\n"
"                 COPYRIGHT (C) 2003-2013 TOMASZ KAxMIERCZAK\n"
"                     COPYRIGHT (C) 2006 KAMIL PAWlOWSKI\n"
"                     COPYRIGHT (C) 2009 MARCIN SeKALSKI\n"
"                    COPYRIGHT (C) 2009 TOMASZ WIsNIEWSKI\n\n"
"CYTADELA IS DISTRIBUTED UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE (GNU\n"
"GPL) EITHER VERSION 3 OF THE LICENSE, OR (AT YOUR OPTION) ANY LATER VERSION.\n"
"CYTADELA COMES WITH ABSOLUTELY NO WARRANTY. SEE THE \"COPYING\" FILE FOR\n"
"DETAILS (THE GNU GPL ITSELF). THE FILE CAN BE FOUND IN THE GAME'S\n"
"DOCUMENTATION DIRECTORY.\n\n"
"CYTADELA IS A CONVERSION OF AN AMIGA GAME ALSO CALLED CYTADELA, CREATED BY\n"
"VIRTUAL DESIGN. THE CONVERSION CONTAINS AN IMPLEMENTATION OF SEVERAL\n"
"ALGORITHMS TAKEN FROM THE ORIGINAL. MAJOR PART OF GRAPHICS, ALL MUSIC, SOUNDS\n"
"AND LEVELS ARE TAKEN FROM THE ORIGINAL, BUT IN SOME CASES THEY ARE PROCESSED\n"
"AND/OR MODIFIED IN ORDER TO MAKE THEM EASIER TO USE WITH THE CONVERSION AND TO\n"
"CORRECT SOME BUGS.\n\n"
"ALL THE ALGORITHMS AND ARTWORK WERE TAKEN FROM THE ORIGINAL WITH PERMISSION\n"
"FROM THEIR AUTHORS. DISTRIBUTION OF THE ARTWORK (AS A PART OF THE CONVERSION)\n"
"IS ALLOWED UNDER THE TERMS OF THE GNU GPL.\n\n\n"
"                     PEOPLE WHO CONTRIBUTED TO THE PROJECT:\n"
"                        (IN ORDER OF ADDING TO THE LIST)\n"
"                     --------------------------------------\n"
"TOMASZ KAxMIERCZAK\n"
"   -PROGRAMMING\n"
"   -SOME 2D GRAPHICS\n"
"   -ADAPTATION OF ORIGINAL 2D/3D GRAPHICS TO THE CITADEL'S ENGINE\n"
"   -GAME DOCUMENTATION (BASED ON THE ORIGINAL DOCUMENTATION)\n"
"   -POLISH, ENGLISH AND GERMAN TRANSLATIONS (BASED ON THE ORIGINAL TRANSLATIONS)\n\n"
"KAMIL PAWlOWSKI\n"
"   -CREATION OF \"CONFIGURE\" AND \"MAKE\" SCRIPTS AND SOME CODE MODIFICATIONS\n"
"    RELATED TO THEM\n\n"
"KRZYSZTOF SMULKOWSKI\n"
"   -LOTS OF TESTING AND BUGTRACKING. THANX!\n\n"
"JOSEF KOROUS\n"
"   -TESTING\n"
"   -CZECH TRANSLATION\n\n"
"MARCIN SeKALSKI\n"
"   -INFO SCREENS FOR TRAINING LEVELS\n"
"   -ALPHA AND BETA TESTING\n"
"   -A LOT OF BUGS FOUND\n"
"   -USEFUL SUGGESTIONS REGARDING THE GAME\n\n"
"KRYSTIAN WlOSEK\n"
"   -CREATION OF DEBIAN PACKAGES\n\n"
"PATRICK DAVID\n"
"   -FRENCH TRANSLATION (GAME AND DOCUMENTATION)\n\n"
"TOMASZ WIsNIEWSKI\n"
"   -HELP WITH ADAPTATION TO BIG-ENDIAN PROCESSORS\n"
"   -CREATION OF MACOS X PACKAGES\n\n"
"RAFAl STEFANOWSKI\n"
"   -BETA TESTING\n\n"
"\n\n"
"                       AUTHORS OF THE ORIGINAL VERSION:\n"
"                       --------------------------------\n"
"                         PAWEl MATUSZ - IDEA AND PROGRAMMING\n"
"                      ARTUR BARDOWSKI - GRAPHICS AND ANIMATIONS\n"
"                   RADOSlAW CZECZOTKA - LEVELS' GRAPHICS\n"
"                          ARTUR OPALA - MUSIC AND SOUND FX\n"
"\n"
"               THERE WERE MANY OTHER PEOPLE WHO CONTRIBUTED TO\n"
"                THE ORIGINAL VERSION, THAT AREN'T LISTED HERE\n"
"\n";

	mDefaultLangInfoText = defaultLang;
	mOtherLangInfoText = otherLang;
}

bool CCytadelaMenu::initMenu(const char **saveNames)
{
	//load all menu images
	//menu background
	const char *mfaFilePath = "tex/Menu.far";
	if(not mSDL->mImgArray.loadImg(mfaFilePath, "menu.tga", mMenuImage[MIMG_MAIN]))
		return false;
	//info background
	if(not mSDL->mImgArray.loadImg(mfaFilePath, "info.tga", mMenuImage[MIMG_INFO]))
		return false;
	//menu cursor
	if(not mSDL->mImgArray.loadImg(mfaFilePath, "menucur.tga", mMenuImage[MIMG_CURSOR]))
		return false;
	//fonts for menu and info
	if(not mSDL->mImgArray.loadImg(mfaFilePath, "infofont.tga", mMenuImage[MIMG_INFOFONT]))
		return false;
	//load font for chosen localization
	char textBuffer[FILENAME_MAX];
	sprintf(textBuffer, "tex/fonts/%s.far", mLocalization->getCurrentLocalization());
	if(not mSDL->mImgArray.loadImg(textBuffer, "menufont.tga", mMenuImage[MIMG_FONT]))
		return false;

	//load menu music
	if(not mSDL->loadMusic("music/Menu.mod"))
		return false;

	//fill the LOAD menu with savenames
	for(int32_t i = 0; i < 5; ++i)
		sprintf(mMenuTexts[MENU_LOAD][i], "%s", saveNames[i]);

	//fill the config-dependant menu positions
	//OPTIONS MENU
	//difficulty
	const char *text;
	if(mConfig->isDifficult())
		text = mLocalization->getText(LOC_MENU_DIFFICULTY_HARD);
	else text = mLocalization->getText(LOC_MENU_DIFFICULTY_EASY);
	sprintf(mMenuTexts[MENU_SETTINGS][0], "%s", text);
	mMenuTextsXOffs[MENU_SETTINGS][0] = 120 - (strlen(text) * 8);
	//screen size
	const int32_t *screenSize = mConfig->getScreenSize();
	sprintf(textBuffer, "%dX%d", screenSize[0], screenSize[1]);
	sprintf(mMenuTexts[MENU_VIDEO][0], "%s", textBuffer);
	mMenuTextsXOffs[MENU_VIDEO][0] = 120 - (strlen(textBuffer) * 8);
	//fullscreen setting
	if(mConfig->isFullScreen())
		text = mLocalization->getText(LOC_MENU_FULLSCREEN);
	else text = mLocalization->getText(LOC_MENU_WINDOWED);
	sprintf(mMenuTexts[MENU_VIDEO][1], "%s", text);
	mMenuTextsXOffs[MENU_VIDEO][1] = 120 - (strlen(text) * 8);

	//SPEED SETTINGS menu
	//get the game speed setting from the config - not used any more
/*	float gameSpeed = mConfig->getGameSpeed();
	//set the text in the menu
	sprintf(mMenuTexts[MENU_GAME_SPEED][0], "%s %.0f%%",
			mLocalization->getText(LOC_MENU_SPEED_GAME), gameSpeed * 100.0f);
	mMenuTextsXOffs[MENU_GAME_SPEED][0] = 120 - (strlen(mMenuTexts[MENU_GAME_SPEED][0]) * 8);*/
	//get the mouse speed setting from the config
	float mouseSpeed = mConfig->getMouseSpeed();
	//set the text in the menu
	sprintf(mMenuTexts[MENU_GAME_SPEED][1], "%s %.1f", mLocalization->getText(LOC_MENU_SPEED_MOUSE), mouseSpeed);
	mMenuTextsXOffs[MENU_GAME_SPEED][1] = 120 - (strlen(mMenuTexts[MENU_GAME_SPEED][1]) * 8);

	//audio settings
	bool audio = mConfig->getAudioStatus();
	sprintf(mMenuTexts[MENU_AUDIO][0], "%s", audio ? mLocalization->getText(LOC_YES) : mLocalization->getText(LOC_NO));
	mMenuTextsXOffs[MENU_AUDIO][0] = 120 - (strlen(mMenuTexts[MENU_AUDIO][0]) * 8);

	//at the begining we are in main menu on the first position
	mMenu = MENU_MAIN;
	mSelItem = 0;
	mCursorFrame = 0;
	return true;
}

void CCytadelaMenu::freeMenu()
{
	mSDL->freeMusic();
	mSDL->mImgArray.free();
}

void CCytadelaMenu::cursorUp()
{
	//set the cursor one position up (-1)
	if(mSelItem == 0)  //if we were on the top - we go to the bottom
		mSelItem = 5;
	else
		mSelItem--;
	updateMenuScreen();
}

void CCytadelaMenu::cursorDown()
{
	//set the cursor one position down (+1)
	if(mSelItem == 5) //if we were on the bottom - we go to the top
		mSelItem = 0;
	else
		mSelItem++;
	updateMenuScreen();
}

MenuAction CCytadelaMenu::enter()
{
	switch(mMenu) {
		case MENU_MAIN: {
			switch(mSelItem) {
				case 0: //start
					return MENUACT_START_GAME;
				case 1: {//load

					mMenu = MENU_LOAD;
					mSelItem = 0;
					updateMenuScreen();
					return MENUACT_CONTINUE;
				}
				case 2: {//options
					mMenu = MENU_SETTINGS;
					mSelItem = 0;
					updateMenuScreen();
					return MENUACT_CONTINUE;
				}
				case 3: {//training
					mMenu = MENU_TRAINING;
					mSelItem = 0;
					updateMenuScreen();
					return MENUACT_CONTINUE;
				}
				case 5: {//info
					mMenu = MENU_INFO;
					updateMenuScreen();
					initInfo();
					displayInfo();
					return MENUACT_CONTINUE;
				}
				default:
					return MENUACT_CONTINUE;
			}
			break;
		}
		case MENU_LOAD: {
			if(mSelItem == 5) {
				mMenu = MENU_MAIN;
				mSelItem = 1;
				updateMenuScreen();
			}
			else if(strcmp(mMenuTexts[MENU_LOAD][mSelItem], mLocalization->getText(LOC_SAVE_EMPTY)) != 0)
				return (MenuAction)(MENUACT_LOAD_1 + mSelItem);
			return MENUACT_CONTINUE;
		}
		case MENU_SETTINGS: {
			switch(mSelItem) {
				case 0: {
					mConfig->setDifficult(not mConfig->isDifficult());
					const char *text;
					if(mConfig->isDifficult())
						text = mLocalization->getText(LOC_MENU_DIFFICULTY_HARD);
					else
						text = mLocalization->getText(LOC_MENU_DIFFICULTY_EASY);
					sprintf(mMenuTexts[MENU_SETTINGS][0], "%s", text);
					mMenuTextsXOffs[MENU_SETTINGS][0] = 120 - (strlen(text) * 8);
					updateMenuScreen();
					break;
				}
				case 1: {
					mMenu = MENU_VIDEO;
					mSelItem = 0;
					updateMenuScreen();
					break;
				}
				case 2: {
					mMenu = MENU_GAME_SPEED;
					mSelItem = 0;
					updateMenuScreen();
					break;
				}
				case 3: {
					mMenu = MENU_AUDIO;
					mSelItem = 0;
					updateMenuScreen();
					break;
				}
				case 5: {
					mMenu = MENU_MAIN;
					mSelItem = 2;
					updateMenuScreen();
					break;
				}
			}
			return MENUACT_CONTINUE;
		}
		case MENU_TRAINING: {
			if(mSelItem == 5) {
				mMenu = MENU_MAIN;
				mSelItem = 3;
				updateMenuScreen();
			}
			else return (MenuAction)(MENUACT_START_TR1 + mSelItem);
			return MENUACT_CONTINUE;
		}
		case MENU_INFO: {
			mMenu = MENU_MAIN;
			updateMenuScreen();
			return MENUACT_CONTINUE;
		}
		case MENU_VIDEO: {
			if(mSelItem == 0)
				changeScreenSize();
			if(mSelItem == 1)
				toggleFullScreen();
			if(mSelItem == 5) {
				mMenu = MENU_SETTINGS;
				mSelItem = 1;
				updateMenuScreen();
			}
			return MENUACT_CONTINUE;
		}
		case MENU_GAME_SPEED: {
			switch(mSelItem) {
/*				case 0:
					changeGameSpeed();
					break;*/
				case 1:
					changeMouseSpeed();
					break;
				case 5: {
					mMenu = MENU_SETTINGS;
					mSelItem = 2;
					updateMenuScreen();
					break;
				}
				default:
					break;
			}
			return MENUACT_CONTINUE;
		}
		case MENU_AUDIO: {
			switch(mSelItem) {
				case 0:
					changeAudioStatus();
					break;
				case 5: {
					mMenu = MENU_SETTINGS;
					mSelItem = 3;
					updateMenuScreen();
					break;
				}
				default:
					break;
			}
			return MENUACT_CONTINUE;
		}
		default:
			return MENUACT_CONTINUE;
	}
	return MENUACT_CONTINUE;
}

void CCytadelaMenu::changeScreenSize()
{
	int32_t actualScreenSizeStrLen = strlen(mMenuTexts[MENU_VIDEO][0]);
	char *width = mMenuTexts[MENU_VIDEO][0], *height = 0;
	for(int32_t i = 0; i < actualScreenSizeStrLen; ++i) {
		if(mMenuTexts[MENU_VIDEO][0][i] == 'X') {
			mMenuTexts[MENU_VIDEO][0][i] = '\0';
			height = &mMenuTexts[MENU_VIDEO][0][i+1];
			break;
		}
	}
	if(height == 0)
		return;

	const ScreenSize *sizes = mSDL->getScreenSizes();
	int32_t screenSizesCount = mSDL->getScreenSizesCount(), i;
	//search for actual screen size in the ScreenSizes array
	for(i = 0; i < screenSizesCount; ++i) {
		if((strcmp(width, sizes[i].resolutionString[0]) == 0) and
			(strcmp(height, sizes[i].resolutionString[1]) == 0))
			break;
	}
	//if not found then change to the first available (can happen if
	//someone edits the configuration file)
	if(i == screenSizesCount)
		i = mSDL->findFirstAvailableScreenSize(0);
	else i = mSDL->findFirstAvailableScreenSize(i);
	mConfig->setScreenSize(sizes[i].resolution[0], sizes[i].resolution[1]);
	sprintf(mMenuTexts[MENU_VIDEO][0], "%dX%d", sizes[i].resolution[0], sizes[i].resolution[1]);
	mMenuTextsXOffs[MENU_VIDEO][0] = 120 - (strlen(mMenuTexts[MENU_VIDEO][0]) * 8);
	updateMenuScreen();
}

void CCytadelaMenu::toggleFullScreen()
{
	const char *text;
	if(mConfig->toggleFullScreen()) {
		mSDL->switchVideoMode(CSDL_DEFAULT_SCREEN_W, CSDL_DEFAULT_SCREEN_H, CSDLClass::Mode2D, CSDLClass::FullScreen);
		text = mLocalization->getText(LOC_MENU_FULLSCREEN);
	} else {
		mSDL->switchVideoMode(CSDL_DEFAULT_SCREEN_W, CSDL_DEFAULT_SCREEN_H, CSDLClass::Mode2D, CSDLClass::Windowed);
		text = mLocalization->getText(LOC_MENU_WINDOWED);
	}
	sprintf(mMenuTexts[MENU_VIDEO][1], "%s", text);
	mMenuTextsXOffs[MENU_VIDEO][1] = 120 - (strlen(text) * 8);
	updateMenuScreen();
}

void CCytadelaMenu::changeGameSpeed()
{
	mConfig->setNextGameSpeed();
	float gameSpeed = mConfig->getGameSpeed();
	sprintf(mMenuTexts[MENU_GAME_SPEED][0], "%s %.0f%%",
			mLocalization->getText(LOC_MENU_SPEED_GAME), gameSpeed * 100.0f);
	updateMenuScreen();
}

void CCytadelaMenu::changeMouseSpeed()
{
	mConfig->setNextMouseSpeed();
	float mouseSpeed = mConfig->getMouseSpeed();
	sprintf(mMenuTexts[MENU_GAME_SPEED][1], "%s %.1f", mLocalization->getText(LOC_MENU_SPEED_MOUSE), mouseSpeed);
	mMenuTextsXOffs[MENU_GAME_SPEED][1] = 120 - (strlen(mMenuTexts[MENU_GAME_SPEED][1]) * 8);
	updateMenuScreen();
}

void CCytadelaMenu::changeAudioStatus()
{
	bool audio = mConfig->changeAudioStatus();
	sprintf(mMenuTexts[MENU_AUDIO][0], "%s", audio ? mLocalization->getText(LOC_YES) : mLocalization->getText(LOC_NO));
	mMenuTextsXOffs[MENU_AUDIO][0] = 120 - (strlen(mMenuTexts[MENU_AUDIO][0]) * 8);
	updateMenuScreen();

	//set in SDL class if the audio should be enabled
	mSDL->setAudioEnabled(audio);
	//try to play the music (this function will check whether the audio is enabled or not)
	mSDL->playMusic(-1);
}

MenuAction CCytadelaMenu::runMenu()
{
	MenuAction action = MENUACT_CONTINUE;
	updateMenuScreen();
	//clear the event queue before starting main loop
	//(we don't process events that happened before displaying menu)
	mSDL->clearEventQueue();
	//play menu music
	mSDL->playMusic(-1);
	mLastTime = mSDL->getTicks();
	//main loop of the menu
	while(action == MENUACT_CONTINUE) {
		SDLKey key = mSDL->readInputMenu();
		//check which events occured
		switch(key) {
			case SDLK_UP: {
				if(mMenu != MENU_INFO)
					cursorUp();
				break;
			}
			case SDLK_DOWN: {
				if(mMenu != MENU_INFO)
					cursorDown();
				break;
			}
			case SDLK_RETURN: {
				action = enter();
				break;
			}
			case SDLK_SPACE: {
				if(mMenu != MENU_INFO)
					action = enter();
				else mScrollInfoText = not mScrollInfoText;
				break;
			}
			case SDLK_ESCAPE: {
				if(mMenu == MENU_MAIN)
					action = MENUACT_EXIT;
				break;
			}
			default:
				break;
		}
		//animate cursor in each frame in menu
		if(mMenu != MENU_INFO)
			animateCursor();
		else
			displayInfo();
	}
	mSDL->blackScreen();
	mSDL->drawFrame();
	mSDL->stopMusic();
	return action;
}

void CCytadelaMenu::updateMenuScreen()
{
	if(mMenu != MENU_INFO) {
		mSDL->displayImage(mMenuImage[MIMG_MAIN], 0, 0, 0);
		for(uint32_t i = 0; i < 6; ++i)
			mSDL->displayText(mMenuImage[MIMG_FONT], mMenuTexts[mMenu][i],
			                  210 + mMenuTextsXOffs[mMenu][i], 164 + i * 30);
	}
	//if entered into new menu, delay next mouse and joy input
	mSDL->delayInput();
	mSDL->drawFrame();
}

void CCytadelaMenu::animateCursor()
{
	uint32_t curTime = mSDL->getTicks();
	uint32_t miliseconds = curTime - mLastTime;
	//now last time is current time minus difference between now and
	//the time when cursor should have been changed (and wasn't, cause
	//something else was beeing done in program)
	mLastTime = curTime - (miliseconds % 70);
	//how many times cursor should have changed since last time
	mCursorFrame += miliseconds / 70;
	while(mCursorFrame >= 18)
		mCursorFrame -= 18;
	SDL_Rect srcRect = {0, mCursorFrame * 16, 288, 16};
	mSDL->displayImage(mMenuImage[MIMG_CURSOR], &srcRect, 184, 168 + (mSelItem) * 30);
	mSDL->drawFrame();
}

void CCytadelaMenu::initInfo()
{
	if(strcmp(mLocalization->getCurrentLocalization(), CYTADELA_DEFAULT_LOCALIZATION) == 0)
		mInfoText = mDefaultLangInfoText;
	else mInfoText = mOtherLangInfoText;

	//calculate the text height - first get the lines count
	size_t textLen = strlen(mInfoText);
	int32_t linesCount = 0;
	for(size_t i = 0; i < textLen; ++i) {
		if(mInfoText[i] == '\n')
			linesCount++;
	}
	//now get the character's height
	const ImgDims *dims = mSDL->mImgArray.getImageDimensions(mMenuImage[MIMG_INFOFONT]);

	assert(dims != 0);

	int32_t charHeight = dims->height / 16;
	//and finally the text height
	mInfoTextHeight = linesCount * (charHeight * 3 / 2);
	//add the screen height so the next sclolling will not begin before
	//the whole text is hidden above the upper screen boundary
	mInfoTextHeight += CSDL_DEFAULT_SCREEN_H;

	//initial settings
	mInfoTextPosition = 0.0f;
	mScrollInfoText = true;
}

void CCytadelaMenu::displayInfo()
{
	uint32_t curTime = mSDL->getTicks();
	uint32_t miliseconds = curTime - mLastTime;
	mLastTime = curTime;
	if(mScrollInfoText)
		mInfoTextPosition += ((float)miliseconds) / 50.0f;
	int32_t infoTextPosition = (int32_t)mInfoTextPosition;
	if(infoTextPosition > mInfoTextHeight)
		mInfoTextPosition = 0.0f;

	//draw the background image and the text
	mSDL->displayImage(mMenuImage[MIMG_INFO], 0, 0, 0);
	mSDL->displayText(mMenuImage[MIMG_INFOFONT], mInfoText, 0, 480-infoTextPosition);
	mSDL->drawFrame();
}
