/* 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/scummsys.h"
#include "mads/game.h"
#include "mads/mads.h"
#include "mads/resources.h"
#include "mads/screen.h"
#include "mads/nebular/menu_nebular.h"

namespace MADS {

namespace Nebular {

#define NEBULAR_MENUSCREEN 990
#define MADS_MENU_Y ((MADS_SCREEN_HEIGHT - MADS_SCENE_HEIGHT) / 2)
#define MADS_MENU_ANIM_DELAY 70

MenuView::MenuView(MADSEngine *vm) : FullScreenDialog(vm) {
	_breakFlag = false;
}

void MenuView::execute() {
	Common::Event event;

	// Main event loop to show the view
	while (!_breakFlag) {
		// Handle events
		while (g_system->getEventManager()->pollEvent(event)) {
			onEvent(event);
		}

		if (_vm->_events->checkForNextFrameCounter()) {
			// Next frame drawn, so allow view to prepare for following one
			doFrame();
		}

		// Slight delay
		g_system->delayMillis(10);
		_breakFlag = _vm->shouldQuit();
	}
}

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

MainMenu::MainMenu(MADSEngine *vm): MenuView(vm) {
	_itemPosList[0] = Common::Point(12, 68);
	_itemPosList[1] = Common::Point(12, 87);
	_itemPosList[2] = Common::Point(12, 107);
	_itemPosList[3] = Common::Point(184, 75);
	_itemPosList[4] = Common::Point(245, 75);
	_itemPosList[5] = Common::Point(184, 99);

	_delayTimeout = 0;
	_menuItem = NULL;
	_menuItemIndex = 0;
	_frameIndex = 0;
	_highlightedIndex = -1;
	_skipFlag = false;
}

MainMenu::~MainMenu() {
	if (_menuItem)
		delete _menuItem;
}

bool MainMenu::onEvent(Common::Event &event) {
	// Handle keypresses - these can be done at any time, even when the menu items are being drawn
	if (event.type == Common::EVENT_KEYDOWN) {
		switch (event.kbd.keycode) {
		case Common::KEYCODE_ESCAPE:
		case Common::KEYCODE_F6:
			handleAction(EXIT);
			break;

		case Common::KEYCODE_F1:
			handleAction(START_GAME);
			break;

		case Common::KEYCODE_F2:
			handleAction(RESUME_GAME);
			break;

		case Common::KEYCODE_F3:
			handleAction(SHOW_INTRO);
			break;

		case Common::KEYCODE_F4:
			handleAction(CREDITS);
			break;

		case Common::KEYCODE_F5:
			handleAction(QUOTES);
			break;

		case Common::KEYCODE_s: {
			// Goodness knows why, but Rex has a key to restart the menuitem animations

			// Delete the current menu items
			if (_menuItem)
				delete _menuItem;
			/*
			_vm->_palette->deleteRange(_bgPalData);
			delete _bgPalData;
			for (uint i = 0; i < _itemPalData.size(); ++i) {
				_vm->_palette->deleteRange(_itemPalData[i]);
				delete _itemPalData[i];
			}
			_itemPalData.clear();
			*/
			// Restart the animation
			_menuItemIndex = 0;
			_skipFlag = false;
			_menuItem = NULL;
			_vm->_events->hideCursor();
			break;
		}

		default:
			// Any other key skips the menu animation
			_skipFlag = true;
			return false;
		}

		return true;
	}

	int menuIndex;

	switch (event.type) {
	case Common::EVENT_LBUTTONDOWN:
		if (_vm->_events->isCursorVisible()) {
			menuIndex = getHighlightedItem(event.mouse.x, event.mouse.y);

			if (menuIndex != _highlightedIndex) {
//				_bgSurface->copyTo(this, Common::Point(0, MADS_MENU_Y));

				_highlightedIndex = menuIndex;
				if (_highlightedIndex != -1) {
					MSprite *spr = _menuItem->getFrame(_highlightedIndex);
					const Common::Point &pt = _itemPosList[_highlightedIndex];
					spr->copyTo(&_vm->_screen, Common::Point(pt.x, MADS_MENU_Y + pt.y));
				}
			}
		} else {
			// Skip the menu animation
			_skipFlag = true;
		}
		return true;

	case Common::EVENT_LBUTTONUP:
		if (_highlightedIndex != -1)
			handleAction((MADSGameAction)_highlightedIndex);
		return true;

	default:
		break;
	}

	return false;
}

void MainMenu::doFrame() {
	int itemSize;

	uint32 currTime = g_system->getMillis();
	if (currTime < _delayTimeout)
		return;
	_delayTimeout = currTime + MADS_MENU_ANIM_DELAY;

	// Rex Nebular handling to cycle through the animated display of the menu items
	if (_menuItemIndex == 7)
		return;

	// If the user has chosen to skip the menu animation, show the menu immediately
	if (_skipFlag && !_vm->_events->isCursorVisible()) {
		// Clear any pending animation
//		_savedSurface.copyTo(&_vm->_screen, Common::Point(0, MADS_MENU_Y));
		
		// Quickly loop through all the menuitems to display each's final frame
		while (_menuItemIndex < 7) {

			if (_menuItem) {
				// Draw the final frame of the menuitem
				MSprite *spr = _menuItem->getFrame(0);
				itemSize = _menuItem->getFrame(0)->h;
				spr->copyTo(&_vm->_screen, Common::Point(_itemPosList[_menuItemIndex - 1].x,
					_itemPosList[_menuItemIndex - 1].y + MADS_MENU_Y + (itemSize / 2) - (spr->h / 2)));

				delete _menuItem;
				//copyTo(_bgSurface, Common::Rect(0, row, width(), row + MADS_SCENE_HEIGHT), 0, 0);
			}

			// Get the next sprite set
			Common::String spritesName = Resources::formatName(NEBULAR_MENUSCREEN, 
				'A', ++_menuItemIndex, EXT_SS, "");
			_menuItem = new SpriteAsset(_vm, spritesName, 0);

			// Slot it into available palette space
/*
			RGBList *palData = _menuItem->getRgbList();
			_vm->_palette->addRange(palData);
			_menuItem->translate(palData, true);
			_itemPalData.push_back(palData);
*/
		}

		_vm->_events->showCursor();
		return;
	}

	if ((_menuItemIndex == 0) || (_frameIndex == 0)) {
		// Get the next menu item
		if (_menuItem) {
			delete _menuItem;

			// Copy over the current display surface area to the background, so the final frame 
			// of the previous menuitem should be kept on the screen
//			copyTo(_bgSurface, Common::Rect(0, row, width(), row + MADS_SCENE_HEIGHT), 0, 0);
		}

		// Get the next menuitem resource
		Common::String spritesName = Resources::formatName(NEBULAR_MENUSCREEN,
			'A', ++_menuItemIndex, EXT_SS, "");

		/*
		//sprintf(resName, "RM%dA%d.SS", REX_MENUSCREEN, ++_menuItemIndex);
		data = _vm->res()->get(resName);
		_menuItem = new SpriteAsset(_vm, data, data->size(), resName);
		_vm->res()->toss(resName);
		*/
		// Slot it into available palette space
		/*
		RGBList *palData = _menuItem->getRgbList();
		_vm->_palette->addRange(palData);
		_menuItem->translate(palData, true);
		_itemPalData.push_back(palData);
		*/
		_frameIndex = _menuItem->getCount() - 1;

		// If the final resource is now loaded, which contains the highlighted versions of 
		// each menuitem, then the startup animation is complete
		if (_menuItemIndex == 7) {
			_vm->_events->showCursor();
			return;
		}
	} else {
		--_frameIndex;
	}

	// Move to the next menuitem frame

	itemSize = _menuItem->getFrame(0)->h;

	//_bgSurface->copyTo(this, 0, row);
	MSprite *spr = _menuItem->getFrame(_frameIndex);
	
	spr->copyTo(&_vm->_screen, 
		Common::Point(_itemPosList[_menuItemIndex - 1].x, 
			_itemPosList[_menuItemIndex - 1].y + MADS_MENU_Y + 
			(itemSize / 2) - (spr->h / 2)));
}

int MainMenu::getHighlightedItem(int x, int y) {
	y -= MADS_MENU_Y;

	for (int index = 0; index < 6; ++index) {
		const Common::Point &pt = _itemPosList[index];
		MSprite *spr = _menuItem->getFrame(index);

		if ((x >= pt.x) && (y >= pt.y) && (x < (pt.x + spr->w)) && (y < (pt.y + spr->h)))
			return index;
	}

	return -1;
}

void MainMenu::handleAction(MADSGameAction action) {
	_vm->_events->hideCursor();
	/*
	switch (action) {
	case START_GAME:
	case RESUME_GAME:
		// Load a sample starting scene - note that, currently, calling loadScene automatically
		// removes this menu screen from being displayed
		_vm->_mouse->cursorOn();
		_vm->_viewManager->addView(_vm->_scene);
		_vm->_scene->loadScene(101);
		return;

	case SHOW_INTRO:
		_vm->_viewManager->showAnimView("@rexopen");
		break;

	case CREDITS:
		_vm->_viewManager->showTextView("credits");
		return;

	case QUOTES:
		_vm->_viewManager->showTextView("quotes");
		return;

	case EXIT:
	{
					// When the Exit action is done from the menu, show one of two possible advertisements

					// Activate the scene display with the specified scene
					bool altAdvert = _vm->_random->getRandomNumber(1000) >= 500;
					_vm->_scene->loadScene(altAdvert ? 995 : 996);
					_vm->_viewManager->addView(_vm->_scene);

					_vm->_viewManager->refreshAll();
					_vm->delay(10000);

					_vm->_events->quitFlag = true;
					return;
	}
		break;
	default:
		break;
	}
	*/
}

} // End of namespace Nebular

} // End of namespace MADS