/* ScummVM - Scumm Interpreter
 * Copyright (C) 2006 The ScummVM project
 *
 * 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.
 *
 * $URL: https://svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-9-1/engines/kyra/kyra3.cpp $
 * $Id: kyra3.cpp 22905 2006-06-03 19:43:57Z eriktorbjorn $
 *
 */

#include "kyra/kyra.h"
#include "kyra/screen.h"
#include "kyra/wsamovie.h"
#include "kyra/sound.h"
#include "kyra/text.h"
#include "kyra/vqa.h"

#include "common/system.h"
#include "common/config-manager.h"

// TODO: Temporary, to get the mouse cursor mock-up working
#include "graphics/cursorman.h"

namespace Kyra {
KyraEngine_v3::KyraEngine_v3(OSystem *system) : KyraEngine(system) {
	_soundDigital = 0;
	_musicSoundChannel = -1;
	_menuAudioFile = "TITLE1.AUD";
}

KyraEngine_v3::~KyraEngine_v3() {
	delete _soundDigital;
}

int KyraEngine_v3::setupGameFlags() {
	_game = GI_KYRA3;
	_lang = 0;
	Common::Language lang = Common::parseLanguage(ConfMan.get("language"));

	switch (lang) {
	case Common::EN_ANY:
	case Common::EN_USA:
	case Common::EN_GRB:
		_lang = 0;
		break;

	case Common::FR_FRA:
		_lang = 1;
		break;

	case Common::DE_DEU:
		_lang = 2;
		break;

	default:
		warning("unsupported language, switching back to English");
		_lang = 0;
		break;
	}

	return 0;
}

Movie *KyraEngine_v3::createWSAMovie() {
	return new WSAMovieV3(this);
}

int KyraEngine_v3::init() {
	KyraEngine::init();
	
	_soundDigital = new SoundDigital(this, _mixer);
	assert(_soundDigital);
	if (!_soundDigital->init())
		error("_soundDigital->init() failed");
	
	uint32 sz;
	_screen->loadFont(Screen::FID_6_FNT, _res->fileData("6.FNT", &sz));
	_screen->loadFont(Screen::FID_8_FNT, _res->fileData("8FAT.FNT", &sz));
	_screen->setScreenDim(0);
	
	return 0;
}

int KyraEngine_v3::go() {
	_screen->_curPage = 0;
	_screen->clearPage(0);
	
	uint8 pal[768];
	memset(pal, 0, sizeof(pal));
	
	WSAMovieV3 *logo = new WSAMovieV3(this);
	logo->open("REVENGE.WSA", 1, pal);
	assert(logo->opened());
	
	pal[0] = pal[1] = pal[2] = 0;
	
	_screen->setScreenPalette(pal);
	
	// XXX
	playMenuAudioFile();
	
	logo->setX(0); logo->setY(0);
	logo->setDrawPage(0);

	for (int i = 0; i < 64 && !_quitFlag; ++i) {
		uint32 nextRun = _system->getMillis() + 3 * _tickLength;
		logo->displayFrame(i);
		_screen->updateScreen();
		delayUntil(nextRun);
	}

	for (int i = 64; i > 29 && !_quitFlag; --i) {
		uint32 nextRun = _system->getMillis() + 3 * _tickLength;
		logo->displayFrame(i);
		_screen->updateScreen();
		delayUntil(nextRun);
	}
	
	switch (handleMainMenu(logo)) {
	case 0:
		break;
	
	case 1:
		playVQA("K3INTRO");
		// TODO: Restart the menu animation
		break;
	
	case 2:
		break;
	
	case 3:
		break;
	
	default:
		break;
	}
	
	delete logo;

	return 0;
}

void KyraEngine_v3::playVQA(const char *name) {
	debugC(9, kDebugLevelMain, "KyraEngine::playVQA('%s')", name);
	VQAMovie vqa(this, _system);

	char filename[20];
	int size = 0;		// TODO: Movie size is 0, 1 or 2.

	snprintf(filename, sizeof(filename), "%s%d.VQA", name, size);

	if (vqa.open(filename)) {
		uint8 pal[768];
		memcpy(pal, _screen->getPalette(0), sizeof(pal));
		if (_screen->_curPage == 0)
			_screen->copyRegion(0, 0, 0, 0, 320, 200, 0, 3);

		_screen->hideMouse();
		_soundDigital->beginFadeOut(_musicSoundChannel);
		_musicSoundChannel = -1;
		_screen->fadeToBlack();
		vqa.setDrawPage(0);
		vqa.play();
		vqa.close();
		_screen->showMouse();

		if (_screen->_curPage == 0)
			_screen->copyRegion(0, 0, 0, 0, 320, 200, 3, 0);
		_screen->setScreenPalette(pal);
	}
}

void KyraEngine_v3::playMenuAudioFile() {
	debugC(9, kDebugLevelMain, "KyraEngine::playMenuAudioFile()");
	if (_soundDigital->isPlaying(_musicSoundChannel))
		return;

	Common::File *handle = new Common::File();
	uint32 temp = 0;
	_res->fileHandle(_menuAudioFile, &temp, *handle);
	if (handle->isOpen()) {
		_musicSoundChannel = _soundDigital->playSound(handle, true);
	}
}

int KyraEngine_v3::handleMainMenu(WSAMovieV3 *logo) {
	debugC(9, kDebugLevelMain, "KyraEngine::handleMainMenu(%p)", (const void*)logo);
	int command = -1;
	
	uint8 colorMap[16];
	memset(colorMap, 0, sizeof(colorMap));
	_screen->setTextColorMap(colorMap);
	
	const char * const *strings = &_mainMenuStrings[_lang << 2];
	Screen::FontId oldFont = _screen->setFont(Screen::FID_8_FNT);
	int charWidthBackUp = _screen->_charWidth;
	
	_screen->_charWidth = -2;
	_screen->setScreenDim(3);
	int backUpX = _screen->_curDim->sx;
	int backUpY = _screen->_curDim->sy;
	int backUpWidth = _screen->_curDim->w;
	int backUpHeight = _screen->_curDim->h;
	_screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 0, 3);

	int x = _screen->_curDim->sx << 3;
	int y = _screen->_curDim->sy;
	int width = _screen->_curDim->w << 3;
	int height =  _screen->_curDim->h;

	drawMainBox(x, y, width, height, 1);
	drawMainBox(x + 1, y + 1, width - 2, height - 2, 0);
	
	int curFrame = 29, frameAdd = 1;
	uint32 nextRun = 0;

	int selected = 0;
	
	drawMainMenu(strings, selected);

#define A 0x00
#define B 0xFF
#define C 0x7F

	// TODO: This is just a mock-up of the real mouse cursor.
	const byte cursorImage[] = {
		A, A, C, C, C, C, C, C, C, C,
		A, B, A, C, C, C, C, C, C, C,
		A, B, B, A, C, C, C, C, C, C,
		A, B, B, B, A, C, C, C, C, C,
		A, B, B, B, B, A, C, C, C, C,
		A, B, B, B, B, B, A, C, C, C,
		A, B, B, B, B, B, B, A, C, C,
		A, B, B, B, B, B, B, B, A, C,
		A, B, B, B, B, B, B, B, B, A,
		C, A, A, A, B, B, B, A, A, C,
		C, C, C, C, A, B, B, B, A, C,
		C, C, C, C, C, A, B, B, B, A,
		C, C, C, C, C, C, A, A, A, C
	};

	_system->warpMouse(300, 180);
	CursorMan.replaceCursor(cursorImage, 10, 13, 1, 1, C);
	_screen->showMouse();

#undef A
#undef B
#undef C

	int fh = _screen->getFontHeight();
	int textPos = ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3;

	Common::Rect menuRect(x + 16, y + 4, x + width - 16, y + 4 + fh * 4);
	
	while (command == -1 && !_quitFlag) {
		// yes 2 * _tickLength here not 3 * like in the first draw
		nextRun = _system->getMillis() + 2 * _tickLength;
		logo->displayFrame(curFrame);
		_screen->updateScreen();
		
		curFrame += frameAdd;
		if (curFrame < 29) {
			curFrame = 29;
			frameAdd = 1;
		} else if (curFrame > 63) {
			curFrame = 64;
			frameAdd = -1;
		}
		
		// XXX
		
		while (_system->getMillis() < nextRun) {
			// XXX
			_screen->updateScreen();
			if ((int32)nextRun - (int32)_system->getMillis() >= 10)
				delay(10);
		}

		if (menuRect.contains(mouseX(), mouseY())) {
			int item = (mouseY() - menuRect.top) / fh;

			if (item != selected) {
				gui_printString(strings[selected], textPos, menuRect.top + selected * fh, 0x80, 0, 5);
				gui_printString(strings[item], textPos, menuRect.top + item * fh, 0xFF, 0, 5);

				selected = item;
			}

			if (_mousePressFlag) {
				// TODO: Flash the text
				command = item;

				// TODO: For now, only the intro is supported
				if (command != 1)
					command = -1;
			}
		}
	}
	
	if (_quitFlag)
		command = -1;
	
	_screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 3, 0);
	_screen->_charWidth = charWidthBackUp;
	_screen->setFont(oldFont);
	
	if (command == 3) {
		_screen->fadeToBlack();
		_soundDigital->stopSound(_musicSoundChannel);
		_musicSoundChannel = -1;
	}
	
	return command;
}

void KyraEngine_v3::drawMainMenu(const char * const *strings, int select) {
	debugC(9, kDebugLevelMain, "KyraEngine::drawMainMenu(%p)", (const void*)strings);
	static const uint16 menuTable[] = { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x80, 0xFF, 0x00, 0x01, 0x02, 0x03 };
	
	int top = _screen->_curDim->sy;
	top += menuTable[1];
	
	for (int i = 0; i < menuTable[3]; ++i) {
		int curY = top + i * _screen->getFontHeight();
		int color = (i == select) ? menuTable[6] : menuTable[5];
		gui_printString(strings[i], ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3, curY, color, 0, 5);
	}
}

void KyraEngine_v3::drawMainBox(int x, int y, int w, int h, int fill) {
	debugC(9, kDebugLevelMain, "KyraEngine::drawMainBox(%d, %d, %d, %d, %d)", x, y, w, h, fill);
	static const uint8 colorTable[] = { 0x16, 0x19, 0x1A, 0x16 };
	--w; --h;

	if (fill) {
		_screen->fillRect(x, y, x+w, y+h, colorTable[0]);
	}
	
	_screen->drawClippedLine(x, y+h, x+w, y+h, colorTable[1]);
	_screen->drawClippedLine(x+w, y, x+w, y+h, colorTable[1]);
	_screen->drawClippedLine(x, y, x+w, y, colorTable[2]);
	_screen->drawClippedLine(x, y, x, y+h, colorTable[2]);
	
	_screen->setPagePixel(_screen->_curPage, x, y+h, colorTable[3]);
	_screen->setPagePixel(_screen->_curPage, x+w, y, colorTable[3]);
}

void KyraEngine_v3::gui_printString(const char *format, int x, int y, int col1, int col2, int flags, ...) {
	debugC(9, kDebugLevelMain, "KyraEngine::gui_printString('%s', %d, %d, %d, %d, %d, ...)", format, x, y, col1, col2, flags);
	if (!format)
		return;
	
	char string[512];
	va_list vaList;
	va_start(vaList, flags);
	vsprintf(string, format, vaList);
	va_end(vaList);
	
	if (flags & 1) {
		x -= _screen->getTextWidth(string) >> 1;
	}
	
	if (flags & 2) {
		x -= _screen->getTextWidth(string);
	}
	
	if (flags & 4) {
		_screen->printText(string, x - 1, y, 240, col2);
		_screen->printText(string, x, y + 1, 240, col2);
	}
	
	if (flags & 8) {
		_screen->printText(string, x - 1, y, 227, col2);
		_screen->printText(string, x, y + 1, 227, col2);
	}
	
	_screen->printText(string, x, y, col1, col2);
}

} // end of namespace Kyra
