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

#include "common/translation.h"

#include "gui/dialog.h"
#include "gui/widget.h"

#include "tsage/tsage.h"
#include "tsage/core.h"
#include "tsage/dialogs.h"
#include "tsage/staticres.h"
#include "tsage/globals.h"
#include "tsage/ringworld2/ringworld2_dialogs.h"
#include "tsage/ringworld2/ringworld2_logic.h"

namespace TsAGE {

namespace Ringworld2 {

/**
 * This dialog implements the right-click dialog
 */
RightClickDialog::RightClickDialog() : GfxDialog() {
	// Setup button positions
	_btnList[0] = Common::Point(48, 12);
	_btnList[1] = Common::Point(31, 29);
	_btnList[2] = Common::Point(65, 29);
	_btnList[3] = Common::Point(14, 47);
	_btnList[4] = Common::Point(48, 47);
	_btnList[5] = Common::Point(83, 47);

	// Set the palette and change the cursor
	_previousCursor = R2_GLOBALS._events.getCursor();
	R2_GLOBALS._events.setCursor(CURSOR_ARROW);

	setPalette();

	// Get the dialog image and selected button images
	if (R2_GLOBALS._sceneManager._sceneNumber == 2900) {
		_surface = surfaceFromRes(2902, 1, 1);
		_btnImages.setVisage(2902, 2);
	} else {
		_surface = surfaceFromRes(1, 1, 1);
		_btnImages.setVisage(1, 2);
	}

	// Set the dialog position
	Rect dialogRect;
	dialogRect.resize(_surface, 0, 0, 100);
	dialogRect.center(g_globals->_events._mousePos.x, g_globals->_events._mousePos.y);

	// Ensure the dialog will be entirely on-screen
	Rect screenRect = g_globals->gfxManager()._bounds;
	screenRect.collapse(4, 4);
	dialogRect.contain(screenRect);

	_bounds = dialogRect;
	_gfxManager._bounds = _bounds;

	_highlightedAction = -1;
	_selectedAction = -1;
}

RightClickDialog::~RightClickDialog() {
}

void RightClickDialog::draw() {
	// Save the covered background area
	_savedArea = surfaceGetArea(g_globals->_gfxManagerInstance.getSurface(), _bounds);

	// Draw the dialog image
	g_globals->gfxManager().copyFrom(_surface, _bounds.left, _bounds.top);
}

bool RightClickDialog::process(Event &event) {
	switch (event.eventType) {
	case EVENT_MOUSE_MOVE: {
		// Check whether a button is highlighted
		int buttonIndex;
		for (buttonIndex = 5; buttonIndex >= 0; --buttonIndex) {
			Rect tempRect(0, 0, 28, 29);
			tempRect.moveTo(_btnList[buttonIndex].x, _btnList[buttonIndex].y);

			if (tempRect.contains(event.mousePos))
				break;
		}
		// If selection has changed, handle it
		if (buttonIndex != _highlightedAction) {
			if (_highlightedAction != -1) {
				// Another button was previously selected, so restore dialog
				_gfxManager.copyFrom(_surface, 0, 0);
			}

			if (buttonIndex != -1) {
				// Draw newly selected button
				GfxSurface btn = _btnImages.getFrame(buttonIndex + 1);
				_gfxManager.copyFrom(btn, _btnList[buttonIndex].x, _btnList[buttonIndex].y);
			}

			_highlightedAction = buttonIndex;
		}

		event.handled = true;
		return true;
	}

	case EVENT_BUTTON_DOWN:
		// Specify the selected action
		_selectedAction = (_highlightedAction == -1) ? 999 : _highlightedAction;
		event.handled = true;
		return true;

	default:
		break;
	}

	return false;
}

int RightClickDialog::execute() {
	// Draw the dialog
	draw();

	// Dialog event handler loop
	_gfxManager.activate();

	while (!g_vm->shouldQuit() && (_selectedAction == -1)) {
		Event evt;
		while (g_globals->_events.getEvent(evt, EVENT_MOUSE_MOVE | EVENT_BUTTON_DOWN)) {
			evt.mousePos.x -= _bounds.left;
			evt.mousePos.y -= _bounds.top;

			process(evt);
		}

		g_system->delayMillis(10);
		GLOBALS._screenSurface.updateScreen();
	}

	// Execute the specified action
	CursorType cursorNum = _previousCursor;
	int result = -1;
	switch (_selectedAction) {
	case 0:
		// Look action
		cursorNum = CURSOR_LOOK;
		break;
	case 1:
		// Walk action
		cursorNum = R2_GLOBALS._player._canWalk ? CURSOR_WALK : CURSOR_USE;
		break;
	case 2:
		// Use action
		cursorNum = CURSOR_USE;
		break;
	case 3:
		// Talk action
		cursorNum = CURSOR_TALK;
		break;
	case 4:
		// Change player
		result = 0;
		break;
	case 5:
		// Options dialog
		result = 1;
		break;
	}

	R2_GLOBALS._events.setCursor(cursorNum);
	_gfxManager.deactivate();

	return result;
}

/*--------------------------------------------------------------------------*/

void CharacterDialog::show() {
	CharacterDialog *dlg = new CharacterDialog();
	CursorType cursorNum = R2_GLOBALS._events.getCursor();

	// Reset the current cursor
	R2_GLOBALS._events.setCursor(CURSOR_ARROW);

	dlg->draw();

	// Make the default button the currently active character
	GfxButton *btn = NULL;
	int oldCharacter = R2_GLOBALS._player._characterIndex;
	switch (oldCharacter) {
	case R2_QUINN:
		btn = &dlg->_btnQuinn;
		break;
	case R2_SEEKER:
		btn = &dlg->_btnSeeker;
		break;
	case R2_MIRANDA:
		btn = &dlg->_btnMiranda;
		break;
	default:
		break;
	}

	// Show the character selection dialog
	btn = dlg->execute(btn);

	// Figure out the new selected character
	if (btn == &dlg->_btnQuinn)
		R2_GLOBALS._player._characterIndex = R2_QUINN;
	else if (btn == &dlg->_btnSeeker)
		R2_GLOBALS._player._characterIndex = R2_SEEKER;
	else if (btn == &dlg->_btnMiranda)
		R2_GLOBALS._player._characterIndex = R2_MIRANDA;

	// Remove the dialog
	dlg->remove();
	delete dlg;

	// Only do transfer if a different character was selected
	if (R2_GLOBALS._player._characterIndex != oldCharacter) {
		// Save the details of the previously active character
		SceneExt *scene = (SceneExt *)R2_GLOBALS._sceneManager._scene;
		scene->saveCharacter(oldCharacter);

		// Play the correctfrequency, if any, of the character being switched to's scanner device
		if (R2_GLOBALS._player._characterScene[R2_NONE] != 300) {
			switch (R2_GLOBALS._scannerFrequencies[R2_GLOBALS._player._characterIndex] - 1) {
			case 0:
				R2_GLOBALS._sound4.stop();
				break;
			case 1:
				R2_GLOBALS._sound4.play(45);
				break;
			case 2:
				R2_GLOBALS._sound4.play(4);
				break;
			case 3:
				R2_GLOBALS._sound4.play(5);
				break;
			case 4:
				R2_GLOBALS._sound4.play(6);
				break;
			default:
				break;
			}
		} else if (R2_GLOBALS._scannerFrequencies[R2_GLOBALS._player._characterIndex] > 1) {
			switch (R2_GLOBALS._scannerFrequencies[R2_GLOBALS._player._characterIndex] - 1) {
			case 2:
				R2_GLOBALS._sound4.play(45);
				break;
			case 3:
				R2_GLOBALS._sound4.play(4);
				break;
			case 4:
				R2_GLOBALS._sound4.play(5);
				break;
			case 5:
				R2_GLOBALS._sound4.play(6);
				break;
			default:
				break;
			}
		} else if ((R2_GLOBALS._player._characterScene[R2_QUINN] == 300) && (R2_GLOBALS._scannerFrequencies[1] != 1)) {
			switch (R2_GLOBALS._scannerFrequencies[1] - 1) {
			case 2:
				R2_GLOBALS._sound4.play(45);
				break;
			case 3:
				R2_GLOBALS._sound4.play(4);
				break;
			case 4:
				R2_GLOBALS._sound4.play(5);
				break;
			case 5:
				R2_GLOBALS._sound4.play(6);
				break;
			default:
				break;
			}
		} else if (R2_GLOBALS._player._characterScene[R2_SEEKER] != 300) {
			R2_GLOBALS._sound4.stop();
		} else if (R2_GLOBALS._scannerFrequencies[2] == 1) {
			R2_GLOBALS._sound4.stop();
		} else {
			switch (R2_GLOBALS._scannerFrequencies[1] - 1) {
			case 2:
				R2_GLOBALS._sound4.play(45);
				break;
			case 3:
				R2_GLOBALS._sound4.play(4);
				break;
			case 4:
				R2_GLOBALS._sound4.play(5);
				break;
			case 5:
				R2_GLOBALS._sound4.play(6);
				break;
			default:
				break;
			}
		}

		// Change to whichever scene the newly selected character is in
		R2_GLOBALS._sceneManager.changeScene(R2_GLOBALS._player._characterScene[R2_GLOBALS._player._characterIndex]);

		// Force the reset the current cursor
		R2_GLOBALS._events.setCursor(CURSOR_USE);

	} else
		// Restore previous cursor
		R2_GLOBALS._events.setCursor(cursorNum);
}

CharacterDialog::CharacterDialog() {
	// Set the element text
	_msgTitle.set(CHAR_TITLE, 140, ALIGN_LEFT);
	_btnQuinn.setText(CHAR_QUINN_MSG);
	_btnSeeker.setText(CHAR_SEEKER_MSG);
	_btnMiranda.setText(CHAR_MIRANDA_MSG);
	_btnCancel.setText(CHAR_CANCEL_MSG);

	// Set position of the elements
	_msgTitle._bounds.moveTo(5, 5);
	_btnQuinn._bounds.moveTo(25, _msgTitle._bounds.bottom + 1);
	_btnSeeker._bounds.moveTo(25, _btnQuinn._bounds.bottom + 1);
	_btnMiranda._bounds.moveTo(25, _btnSeeker._bounds.bottom + 1);
	_btnCancel._bounds.moveTo(25, _btnMiranda._bounds.bottom + 1);

	// Add the items to the dialog
	addElements(&_msgTitle, &_btnQuinn, &_btnSeeker, &_btnMiranda, &_btnCancel, NULL);

	// Set the dialog size and position
	frame();
	_bounds.collapse(-6, -6);
	setCenter(160, 100);
}

/*--------------------------------------------------------------------------*/

void HelpDialog::show() {
	// change the cursor
	R2_GLOBALS._events.setCursor(CURSOR_ARROW);

	// Create the dialog and draw it
	HelpDialog *dlg = new HelpDialog();
	dlg->draw();

	// Show the help dialog
	GfxButton *btn = dlg->execute(&dlg->_btnResume);

	// If a function button was selected, take care of it
	Event evt;
	evt.eventType = EVENT_KEYPRESS;
	evt.kbd.keycode = Common::KEYCODE_INVALID;
	if (btn == &dlg->_btnList[0]) {
		evt.kbd.keycode = Common::KEYCODE_F2;
	} else if (btn == &dlg->_btnList[1]) {
		evt.kbd.keycode = Common::KEYCODE_F3;
	} else if (btn == &dlg->_btnList[2]) {
		evt.kbd.keycode = Common::KEYCODE_F4;
	} else if (btn == &dlg->_btnList[3]) {
		evt.kbd.keycode = Common::KEYCODE_F5;
	} else if (btn == &dlg->_btnList[4]) {
		evt.kbd.keycode = Common::KEYCODE_F7;
	} else if (btn == &dlg->_btnList[5]) {
		evt.kbd.keycode = Common::KEYCODE_F8;
	} else if (btn == &dlg->_btnList[6]) {
		evt.kbd.keycode = Common::KEYCODE_F10;
	}

	// Remove the dialog
	dlg->remove();
	delete dlg;

	// If a action button was selected, dispatch to handle it
	if (evt.kbd.keycode != Common::KEYCODE_INVALID)
		R2_GLOBALS._game->processEvent(evt);
	else
		R2_GLOBALS._events.setCursorFromFlag();
}

HelpDialog::HelpDialog() {
	// Set the title and game version
	_msgTitle.set(HELP_MSG, 172, ALIGN_CENTER);
	_msgTitle._bounds.moveTo(5, 0);
	_msgVersion.set(GAME_VERSION, 172, ALIGN_CENTER);
	_msgVersion._bounds.moveTo(5, _msgTitle._bounds.bottom + 3);
	addElements(&_msgTitle, &_msgVersion, NULL);

	// Set buttons
	_btnList[0].setText(F2);
	_btnList[0]._bounds.moveTo(5, _msgVersion._bounds.bottom + 2);
	_btnDescription[0].set(SOUND_OPTIONS, 140, ALIGN_LEFT);
	_btnDescription[0]._bounds.moveTo(_btnList[0]._bounds.right + 2, _btnList[0]._bounds.top + 4);

	_btnList[1].setText(F3);
	_btnList[1]._bounds.moveTo(5, _btnList[0]._bounds.bottom);
	_btnDescription[1].set(QUIT_GAME, 140, ALIGN_LEFT);
	_btnDescription[1]._bounds.moveTo(_btnList[1]._bounds.right + 2, _btnList[1]._bounds.top + 4);

	_btnList[2].setText(F4);
	_btnList[2]._bounds.moveTo(5, _btnList[1]._bounds.bottom);
	_btnDescription[2].set(RESTART_GAME, 140, ALIGN_LEFT);
	_btnDescription[2]._bounds.moveTo(_btnList[2]._bounds.right + 2, _btnList[2]._bounds.top + 4);

	_btnList[3].setText(F5);
	_btnList[3]._bounds.moveTo(5, _btnList[2]._bounds.bottom);
	_btnDescription[3].set(SAVE_GAME, 140, ALIGN_LEFT);
	_btnDescription[3]._bounds.moveTo(_btnList[3]._bounds.right + 2, _btnList[3]._bounds.top + 4);

	_btnList[4].setText(F7);
	_btnList[4]._bounds.moveTo(5, _btnList[3]._bounds.bottom);
	_btnDescription[4].set(RESTORE_GAME, 140, ALIGN_LEFT);
	_btnDescription[4]._bounds.moveTo(_btnList[4]._bounds.right + 2, _btnList[4]._bounds.top + 4);

	_btnList[5].setText(F8);
	_btnList[5]._bounds.moveTo(5, _btnList[4]._bounds.bottom);
	_btnDescription[5].set(SHOW_CREDITS, 140, ALIGN_LEFT);
	_btnDescription[5]._bounds.moveTo(_btnList[5]._bounds.right + 2, _btnList[5]._bounds.top + 4);

	_btnList[6].setText(F10);
	_btnList[6]._bounds.moveTo(5, _btnList[5]._bounds.bottom);
	_btnDescription[6].set(PAUSE_GAME, 140, ALIGN_LEFT);
	_btnDescription[6]._bounds.moveTo(_btnList[6]._bounds.right + 2, _btnList[6]._bounds.top + 4);

	for (int i = 0; i < 7; ++i) {
		addElements(&_btnList[i], &_btnDescription[i], NULL);
	}

	// Add 'Resume' button
	_btnResume.setText(RESUME_PLAY);
	_btnResume._bounds.moveTo(5, _btnList[6]._bounds.bottom + 2);
	addElements(&_btnResume, NULL);

	// Set the dialog size and position
	frame();
	_bounds.collapse(-6, -6);
	setCenter(160, 100);
}

bool HelpDialog::handleKeypress(Event &event, GfxButton *&btn) {
	switch (event.kbd.keycode) {
	case Common::KEYCODE_F2:
		btn = &_btnList[0];
		break;
	case Common::KEYCODE_F3:
		btn = &_btnList[1];
		break;
	case Common::KEYCODE_F4:
		btn = &_btnList[2];
		break;
	case Common::KEYCODE_F5:
		btn = &_btnList[3];
		break;
	case Common::KEYCODE_F7:
		btn = &_btnList[4];
		break;
	case Common::KEYCODE_F8:
		btn = &_btnList[5];
		break;
	case Common::KEYCODE_F10:
		btn = &_btnList[6];
		break;
	default:
		return false;
	}

	return true;
}

} // End of namespace Ringworld2

} // End of namespace TsAGE