/* REminiscence - Flashback interpreter
 * Copyright (C) 2005-2007 Gregory Montoir
 *
 * 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "game.h"
#include "mod_player.h"
#include "resource.h"
#include "systemstub.h"
#include "video.h"
#include "menu.h"


Menu::Menu(ModPlayer *ply, Resource *res, SystemStub *stub, Video *vid)
        : _ply(ply), _res(res), _stub(stub), _vid(vid) {
}

void Menu::drawString(const char *str, int16 y, int16 x, uint8 color) {
	debug(DBG_MENU, "Menu::drawString()");
	uint8 v1b = _vid->_charFrontColor;
	uint8 v2b = _vid->_charTransparentColor;
	uint8 v3b = _vid->_charShadowColor;
	switch (color) {
	case 0:
		_vid->_charFrontColor = _charVar1;
		_vid->_charTransparentColor = _charVar2;
		_vid->_charShadowColor = _charVar2;
		break;
	case 1:
		_vid->_charFrontColor = _charVar2;
		_vid->_charTransparentColor = _charVar1;
		_vid->_charShadowColor = _charVar1;
		break;
	case 2:
		_vid->_charFrontColor = _charVar3;
		_vid->_charTransparentColor = 0xFF;
		_vid->_charShadowColor = _charVar1;
		break;
	case 3:
		_vid->_charFrontColor = _charVar4;
		_vid->_charTransparentColor = 0xFF;
		_vid->_charShadowColor = _charVar1;
		break;
	case 4:
		_vid->_charFrontColor = _charVar2;
		_vid->_charTransparentColor = 0xFF;
		_vid->_charShadowColor = _charVar1;
		break;
	case 5:
		_vid->_charFrontColor = _charVar2;
		_vid->_charTransparentColor = 0xFF;
		_vid->_charShadowColor = _charVar5;
		break;
	}
	
	drawString2(str, y, x);
	
	_vid->_charFrontColor = v1b;
	_vid->_charTransparentColor = v2b;
	_vid->_charShadowColor = v3b;
}

void Menu::drawString2(const char *str, int16 y, int16 x) {
	debug(DBG_MENU, "Menu::drawString2()");
	int len = 0;
	while (*str) {
		_vid->drawChar((uint8)*str, y, x + len);
		++str;
		++len;
	}
	_vid->markBlockAsDirty(x * 8, y * 8, len * 8, 8);
}

void Menu::loadPicture(const char *prefix) {
	debug(DBG_MENU, "Menu::loadPicture('%s')", prefix);
	_res->load_MAP_menu(prefix, _res->_memBuf);
	for (int i = 0; i < 4; ++i) {
		for (int y = 0; y < 224; ++y) {
			for (int x = 0; x < 64; ++x) {
				_vid->_frontLayer[i + x * 4 + 256 * y] = _res->_memBuf[0x3800 * i + x + 64 * y];
			}
		}
	}
	_res->load_PAL_menu(prefix, _res->_memBuf);
	_stub->setPalette(_res->_memBuf, 256);
}

void Menu::handleInfoScreen() {
	debug(DBG_MENU, "Menu::handleInfoScreen()");
	_vid->fadeOut();
	switch (_res->_ver) {
	case VER_FR:
		loadPicture("instru_f");
		break;
	case VER_EN:
	case VER_DE:
	case VER_SP:
	case VER_IT:
		loadPicture("instru_e");
		break;
	}
	_vid->fullRefresh();
	_vid->updateScreen();
	do {
		_stub->sleep(EVENTS_DELAY);
		_stub->processEvents();
		if (_stub->_pi.enter) {
			_stub->_pi.enter = false;
			break;
		}
	} while (!_stub->_pi.quit);
}

bool Menu::handlePasswordScreen(uint8 &new_skill, uint8 &new_level) {
	debug(DBG_MENU, "Menu::handlePasswordScreen()");
        static const uint8 option_colors[3][3] = {{2,3,3},{3,2,3},{3,3,2}};
	_vid->fadeOut();
        loadPicture("menu2");             
	_vid->fullRefresh();
        drawString(_res->getMenuString(LocaleData::LI_12_SKILL_LEVEL), 22, 5, 3);
	int skill_level = new_skill;
        new_level=0;
		const char *levels[]={
			"Titan/The Jungle",
			"Titan/New Washington",
			"Titan/Death Tower Show",
			"Earth/Surface",
			"Earth/Paradise Club",
			"Planet Morphs/Surface",
			"Planet Morphs/Inner Core"
			};
			
			drawString(_res->getMenuString(LocaleData::LI_06_LEVEL), 5, 5, 3);
			
        do {
			for (int i = 0; i < 7; ++i) 
			 drawString(levels[i], 7 + i*2, 4, (i == new_level) ? 2 : 3);

			drawString(_res->getMenuString(LocaleData::LI_13_EASY),   24,  4, option_colors[skill_level][0]);
			drawString(_res->getMenuString(LocaleData::LI_14_NORMAL), 24, 14, option_colors[skill_level][1]);
			drawString(_res->getMenuString(LocaleData::LI_15_EXPERT), 24, 24, option_colors[skill_level][2]);

			_vid->updateScreen();
			_stub->sleep(EVENTS_DELAY);
			_stub->processEvents();

			if (_stub->_pi.dirMask & PlayerInput::DIR_LEFT) {
				_stub->_pi.dirMask &= ~PlayerInput::DIR_LEFT;
				if (skill_level == 0)
					skill_level = 2;
				else
					--skill_level;
			}
				
			if (_stub->_pi.dirMask & PlayerInput::DIR_RIGHT) {
				_stub->_pi.dirMask &= ~PlayerInput::DIR_RIGHT;
				if (skill_level == 2)
					skill_level = 0;
				else
					++skill_level;
			}
			
			if (_stub->_pi.dirMask & PlayerInput::DIR_UP) {
				_stub->_pi.dirMask &= ~PlayerInput::DIR_UP;
				if (new_level == 0)
					new_level = 6;
				else
					--new_level;
			}

			if (_stub->_pi.dirMask & PlayerInput::DIR_DOWN) {
				_stub->_pi.dirMask &= ~PlayerInput::DIR_DOWN;
				if (new_level == 6)
					new_level = 0;
				else
					++new_level;
			}

			if (_stub->_pi.enter) {
				_stub->_pi.enter = false;
				new_skill = skill_level;
                return true;
			}
			
	} while (!_stub->_pi.quit);
	new_skill = 1;
	return false;
}

void Menu::handleSkillScreen(uint8 &new_skill) {
	debug(DBG_MENU, "Menu::handlePasswordScreen()");
	_vid->fadeOut();
    loadPicture("menu3");             
	_vid->fullRefresh();
    new_skill=0;
	const char *levels[]={
		"FRENCH",
		"ENGLISH",
		"GERMAN",
		"SPANISH",
		"ITALIAN"
	};
			
	do {
		for (uint8 i = 0; i < ARRAYSIZE(levels); ++i)
		 drawString(levels[i], 9 + i*2, 14, (i == new_skill) ? 2 : 3);

		_vid->updateScreen();
		_stub->sleep(EVENTS_DELAY);
		_stub->processEvents();

		if (_stub->_pi.dirMask & PlayerInput::DIR_UP) {
				_stub->_pi.dirMask &= ~PlayerInput::DIR_UP;
				if (new_skill == 0)
					new_skill = ARRAYSIZE(levels)-1;
				else
					--new_skill;
		}
		
		if (_stub->_pi.dirMask & PlayerInput::DIR_DOWN) {
				_stub->_pi.dirMask &= ~PlayerInput::DIR_DOWN;
				if (new_skill == ARRAYSIZE(levels)-1)
					new_skill = 0;
				else
					++new_skill;
		}

		if (_stub->_pi.enter) {
			_stub->_pi.enter = false;
			return;
		}
	} while (!_stub->_pi.quit);
}

bool Menu::handleTitleScreen(uint8 &new_skill, uint8 &new_level) {
	debug(DBG_MENU, "Menu::handleTitleScreen()");
	bool quit_loop = false;
	int menu_entry = 0;
	bool reinit_screen = true;
	bool continue_game = true;
	_charVar1 = 0;
	_charVar2 = 0;
	_charVar3 = 0;
	_charVar4 = 0;
	_charVar5 = 0;
	_ply->play(1);
	while (!quit_loop) {
		if (reinit_screen) {
			_vid->fadeOut();
			loadPicture("menu1");
			_vid->fullRefresh();
			_charVar3 = 1;
			_charVar4 = 2;
			menu_entry = 0;
			reinit_screen = false;
		}
		int selected_menu_entry = -1;
		for (int i = 0; i < 5; ++i) {
			int color = (i == menu_entry) ? 2 : 3;
			drawString(_res->getMenuString(LocaleData::LI_07_START + i), 16 + i * 2, 20, color);
		}

		_vid->updateScreen();
		_stub->sleep(EVENTS_DELAY);
		_stub->processEvents();
		
		if (_stub->_pi.dirMask & PlayerInput::DIR_UP) {
			_stub->_pi.dirMask &= ~PlayerInput::DIR_UP;
			if (menu_entry != 0) {
				--menu_entry;
			} else {
				menu_entry = 4;
			}
		}
		if (_stub->_pi.dirMask & PlayerInput::DIR_DOWN) {
			_stub->_pi.dirMask &= ~PlayerInput::DIR_DOWN;
			if (menu_entry != 4) {
				++menu_entry;
			} else {
				menu_entry = 0;
			}
		}
		if (_stub->_pi.enter) {
			_stub->_pi.enter = false;
			selected_menu_entry = menu_entry;
		}
		
		if (selected_menu_entry != -1) {
			switch (selected_menu_entry) {
			case MENU_OPTION_ITEM_START:
				new_level = 0;
                new_skill = 1;
				quit_loop = true;
				break;
            case MENU_OPTION_ITEM_SKILL: //choose level
				new_level = 0;
                new_skill = 1;
				if (handlePasswordScreen(new_skill, new_level)) {
					quit_loop = true;
				} else {
					reinit_screen = true;
				}
				break;
			case MENU_OPTION_ITEM_PASSWORD: //choose language
                new_skill=_res->_ver;
                handleSkillScreen(new_skill);
                _res->_ver=(Version)new_skill;
				_res->load_TEXT();
				_res->load_CINE();
                reinit_screen = true;
				break;
			case MENU_OPTION_ITEM_INFO:
				handleInfoScreen();
				reinit_screen = true;
				break;
			case MENU_OPTION_ITEM_QUIT:
				continue_game = false;
				quit_loop = true;
				break;
			}
		}
		if (_stub->_pi.quit) {
			continue_game = false;
			quit_loop = true;
			break;
		}
	}
	_ply->stop();
	return continue_game;
}
