/* 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 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://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-11-0/engines/parallaction/gui_ns.cpp $
 * $Id: gui_ns.cpp 30459 2008-01-12 23:07:51Z sev $
 *
 */

#include "common/system.h"

#include "parallaction/parallaction.h"
#include "parallaction/sound.h"


namespace Parallaction {

const char *introMsg1[] = {
	"INSERISCI IL CODICE",
	"ENTREZ CODE",
	"ENTER CODE",
	"GIB DEN KODE EIN"
};

const char *introMsg2[] = {
	"CODICE ERRATO",
	"CODE ERRONE",
	"WRONG CODE",
	"GIB DEN KODE EIN"
};

const char *introMsg3[] = {
	"PRESS LEFT MOUSE BUTTON",
	"TO SEE INTRO",
	"PRESS RIGHT MOUSE BUTTON",
	"TO START"
};

const char *newGameMsg[] = {
	"NUOVO GIOCO",
	"NEUF JEU",
	"NEW GAME",
	"NEUES SPIEL"
};

const char *loadGameMsg[] = {
	"GIOCO SALVATO",
	"JEU SAUVE'",
	"SAVED GAME",
	"SPIEL GESPEICHERT"
};


#define BLOCK_WIDTH 	16
#define BLOCK_HEIGHT	24

#define BLOCK_X 		112
#define BLOCK_Y 		130

#define BLOCK_SELECTION_X		  (BLOCK_X-1)
#define BLOCK_SELECTION_Y		  (BLOCK_Y-1)

#define BLOCK_X_OFFSET	(BLOCK_WIDTH+1)
#define BLOCK_Y_OFFSET	9

//	destination slots for code blocks
//
#define SLOT_X			61
#define SLOT_Y			64
#define SLOT_WIDTH		(BLOCK_WIDTH+2)

#define PASSWORD_LEN	6

#define CHAR_DINO       0
#define CHAR_DONNA      1
#define CHAR_DOUGH      2

static const uint16 _amigaKeys[][PASSWORD_LEN] = {
	{ 5, 3, 6, 2, 2, 7 },		// dino
	{ 0, 3, 6, 2, 2, 6 },		// donna
	{ 1, 3 ,7, 2, 4, 6 }		// dough
};

static const uint16 _pcKeys[][PASSWORD_LEN] = {
	{ 5, 3, 6, 1, 4, 7 },		// dino
	{ 0, 2, 8, 5, 5, 1 },		// donna
	{ 1, 7 ,7, 2, 2, 6 }		// dough
};

static const char *_charStartLocation[] = {
	"test.dino",
	"test.donna",
	"test.dough"
};

enum {
	NEW_GAME,
	LOAD_GAME
};

enum {
	START_DEMO,
	START_INTRO,
	GAME_LOADED,
	SELECT_CHARACTER
};

void Parallaction_ns::guiStart() {

	_disk->selectArchive((getFeatures() & GF_LANG_MULT) ? "disk1" : "disk0");

	guiSplash();

	_gfx->setFont(_introFont);
	_gfx->setFontShadow(true);

	_language = guiChooseLanguage();
	_disk->setLanguage(_language);

	int event;

	if (getFeatures() & GF_DEMO) {
		event = START_DEMO;
	} else {
		if (guiSelectGame() == NEW_GAME) {
			event = guiNewGame();
		} else {
			event = loadGame() ? GAME_LOADED : START_INTRO;
		}
	}

	switch (event) {
	case START_DEMO:
		strcpy(_location._name, "fognedemo.dough");
		break;

	case START_INTRO:
		strcpy(_location._name, "fogne.dough");
		break;

	case GAME_LOADED:
		// nothing to do here
		return;

	case SELECT_CHARACTER:
		selectStartLocation();
		break;

	}

	return;
}

void Parallaction_ns::selectStartLocation() {
	int character = guiSelectCharacter();
	if (character == -1)
		error("invalid character selected from menu screen");

	scheduleLocationSwitch(_charStartLocation[character]);
}


void Parallaction_ns::guiSplash() {

	showSlide("intro");
	_gfx->updateScreen();
	g_system->delayMillis(2000);

	showSlide("minintro");
	_gfx->updateScreen();
	g_system->delayMillis(2000);

}

int Parallaction_ns::guiNewGame() {

	const char **v14 = introMsg3;

    _gfx->setFont(_menuFont);
    _gfx->setFontShadow(true);

	_disk->selectArchive("disk1");

	setBackground("test", NULL, NULL);

	_gfx->swapBuffers();

	_gfx->displayCenteredString(50, v14[0]);
	_gfx->displayCenteredString(70, v14[1]);
	_gfx->displayCenteredString(100, v14[2]);
	_gfx->displayCenteredString(120, v14[3]);

	showCursor(false);

	_gfx->updateScreen();

	_mouseButtons = kMouseNone;
	do {
		readInput();
	} while (_mouseButtons != kMouseLeftUp && _mouseButtons != kMouseRightUp);

	showCursor(true);

	if (_mouseButtons != kMouseRightUp) {
		return START_INTRO;
	}

	return SELECT_CHARACTER;
}

static const Common::Rect _dosLanguageSelectBlocks[4] = {
	Common::Rect(  80, 110, 128, 180 ),	// Italian
	Common::Rect( 129,  85, 177, 155 ),	// French
	Common::Rect( 178,  60, 226, 130 ),	// English
	Common::Rect( 227,  35, 275, 105 )	// German
};

static const Common::Rect _amigaLanguageSelectBlocks[4] = {
	Common::Rect(  -1,  -1,  -1,  -1 ),	// Italian: not supported by Amiga multi-lingual version
	Common::Rect( 129,  85, 177, 155 ),	// French
	Common::Rect( 178,  60, 226, 130 ),	// English
	Common::Rect( 227,  35, 275, 105 )	// German
};


uint16 Parallaction_ns::guiChooseLanguage() {

	const Common::Rect *blocks;

	if (getPlatform() == Common::kPlatformAmiga) {
		if (!(getFeatures() & GF_LANG_MULT)) {
			if (getFeatures() & GF_DEMO) {
				return 1;		// Amiga Demo supports English
			} else {
				return 0;		// The only other non multi-lingual version just supports Italian
			}
		}

		blocks = _amigaLanguageSelectBlocks;
	} else {
		blocks = _dosLanguageSelectBlocks;
	}

	// user can choose language in dos version
	showSlide("lingua");
	_gfx->displayString(60, 30, "SELECT LANGUAGE", 1);
	setArrowCursor();

	int selection = -1;
	while (selection == -1) {
		waitUntilLeftClick();
		for (uint16 i = 0; i < 4; i++) {
			if (blocks[i].contains(_mousePos)) {
				selection = i;
				break;
			}
		}
	}

	beep();

	return selection;
}



uint16 Parallaction_ns::guiSelectGame() {
//	  printf("selectGame()\n");

	showSlide("restore");

	uint16 _si = 0;
	uint16 _di = 3;

	_mouseButtons = kMouseNone;
	while (_mouseButtons != kMouseLeftUp) {

		readInput();

		_si = (_mousePos.x > 160) ? 1 : 0;

		if (_si != _di) {
			_di = _si;

			_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
			if (_si != 0) {
				// load a game
				_gfx->displayString(60, 30, loadGameMsg[_language], 1);
			} else {
				// new game
				_gfx->displayString(60, 30, newGameMsg[_language], 1);
			}

		}

		_gfx->updateScreen();
		g_system->delayMillis(30);
	}

	return _si ? LOAD_GAME : NEW_GAME;
}

static const Common::Rect codeSelectBlocks[9] = {
	Common::Rect( 111, 129, 127, 153 ),		// na
	Common::Rect( 128, 120, 144, 144 ),		// wa
	Common::Rect( 145, 111, 161, 135 ),		// ra
	Common::Rect( 162, 102, 178, 126 ),		// ri
	Common::Rect( 179, 93, 195, 117 ),		// i
	Common::Rect( 196, 84, 212, 108 ),		// ne
	Common::Rect( 213, 75, 229, 99 ),		// ho
	Common::Rect( 230, 66, 246, 90 ),		// ki
	Common::Rect( 247, 57, 263, 81 )		// ka
};

static const Common::Rect codeTrueBlocks[9] = {
	Common::Rect( 112, 130, 128, 154 ),
	Common::Rect( 129, 121, 145, 145 ),
	Common::Rect( 146, 112, 162, 136 ),
	Common::Rect( 163, 103, 179, 127 ),
	Common::Rect( 180, 94, 196, 118 ),
	Common::Rect( 197, 85, 213, 109 ),
	Common::Rect( 214, 76, 230, 100 ),
	Common::Rect( 231, 67, 247, 91 ),
	Common::Rect( 248, 58, 264, 82 )
};


int Parallaction_ns::guiGetSelectedBlock(const Common::Point &p) {

	int selection = -1;

	for (uint16 i = 0; i < 9; i++) {
		if (codeSelectBlocks[i].contains(p)) {
			selection = i;
			break;
		}
	}

	if ((selection != -1) && (getPlatform() == Common::kPlatformAmiga)) {
		_gfx->invertRect(Gfx::kBitFront, codeTrueBlocks[selection]);
		_gfx->updateScreen();
		beep();
		g_system->delayMillis(100);
		_gfx->invertRect(Gfx::kBitFront, codeTrueBlocks[selection]);
		_gfx->updateScreen();
	}

	return selection;
}


//
//	character selection and protection
//
int Parallaction_ns::guiSelectCharacter() {
	debugC(1, kDebugMenu, "Parallaction_ns::guiselectCharacter()");

	Graphics::Surface v14;
	v14.create(BLOCK_WIDTH, BLOCK_HEIGHT, 1);

	setArrowCursor();
	_soundMan->stopMusic();

	_gfx->setFont(_introFont);
	_gfx->setFontShadow(true);

	_disk->selectArchive((getFeatures() & GF_LANG_MULT) ? "disk1" : "disk0");

	showSlide("password");	// loads background into kBitBack buffer


	const uint16 (*keys)[PASSWORD_LEN] = (getPlatform() == Common::kPlatformAmiga && (getFeatures() & GF_LANG_MULT)) ? _amigaKeys : _pcKeys;
	uint16 _di = 0;
    byte points[3] = { 0, 0, 0 };

    bool fail;

	while (true) {

        points[0] = 0;
        points[1] = 0;
        points[2] = 0;
        fail = false;

		_gfx->displayString(60, 30, introMsg1[_language], 1);			// displays message

		_di = 0;
		while (_di < PASSWORD_LEN) {

			waitUntilLeftClick();
			int _si = guiGetSelectedBlock(_mousePos);

			if (_si != -1) {
				_gfx->grabRect((byte*)v14.pixels, codeTrueBlocks[_si], Gfx::kBitFront, BLOCK_WIDTH);
				_gfx->flatBlitCnv(&v14, _di * SLOT_WIDTH + SLOT_X, SLOT_Y, Gfx::kBitFront);

                if (keys[0][_di] == _si) {
                    points[0]++;
                } else
                if (keys[1][_di] == _si) {
                    points[1]++;
                } else
                if (keys[2][_di] == _si) {
                    points[2]++;
                } else {
                    fail = true;
                }

                // build user preference
                points[0] += (keys[0][_di] == _si);
                points[1] += (keys[1][_di] == _si);
                points[2] += (keys[2][_di] == _si);

                _di++;
			}

		}

        if (!fail) {
            break;
        }

		_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
		_gfx->displayString(60, 30, introMsg2[_language], 1);
		_gfx->updateScreen();

		g_system->delayMillis(2000);

		_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
	}

	_gfx->setBlackPalette();
	_gfx->updateScreen();

	v14.free();


    // actually select character

	int character = -1;
	if (points[0] >= points[1] && points[0] >= points[2]) {
        character = CHAR_DINO;
	} else
	if (points[1] >= points[0] && points[1] >= points[2]) {
        character = CHAR_DONNA;
	} else
	if (points[2] >= points[0] && points[2] >= points[1]) {
        character = CHAR_DOUGH;
	} else {
        error("If you read this, either your CPU or transivity is broken (we believe the former).");
	}

    return character;
}


} // namespace Parallaction
