/* 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 3 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, see <http://www.gnu.org/licenses/>.
 *
 */

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

#include "engines/metaengine.h"

#include "graphics/macgui/macwindowmanager.h"
#include "graphics/macgui/macmenu.h"

#include "gui/message.h"

#include "pink/pink.h"
#include "pink/screen.h"
#include "pink/objects/actors/lead_actor.h"

namespace Pink {

enum {
	kNewGameAction			= 57600,
	kLoadSave				= 57601,
	kSaveAction				= 57603,
	kSaveAsAction			= 57604,
	kSongsAction			= 32865,
	kSoundSettingsAction	= 32772,
	kLastSavesAction		= 57616,
	kPauseAction			= 32854,
	kExitAction				= 57665
};

enum {
	kShowContent	= 32771,
	kShowGreece		= 32866,
	kShowIndonesia  = 32867,
	kShowIsrael		= 32868,
	kShowKenya		= 32869,
	kShowRussia		= 32870
};

enum {
	kShowPDAAction			= 32793,

	kShowAustraliaArt		= 32796,
	kShowAustraliaCloth		= 32797,
	kShowAustraliaFood		= 32798,
	kShowAustraliaHistory	= 32799,
	kShowAustraliaNature	= 32800,
	kShowAustraliaPeople	= 32801,
	kShowAustraliaPlaces	= 32802,
	kShowAustraliaReligion	= 32803,

	kShowBhutanArt			= 32804,
	kShowBhutanCloth		= 32805,
	kShowBhutanFood			= 32806,
	kShowBhutanHistory		= 32807,
	kShowBhutanNature		= 32808,
	kShowBhutanPeople		= 32809,
	kShowBhutanPlaces		= 32810,
	kShowBhutanReligion		= 32811,

	kShowChinaArt 			= 32812,
	kShowChinaCloth			= 32813,
	kShowChinaFood			= 32814,
	kShowChinaHistory		= 32815,
	kShowChinaNature		= 32816,
	kShowChinaPeople		= 32817,
	kShowChinaPlaces		= 32818,
	kShowChinaReligion		= 32819,

	kShowEnglandArt			= 32820,
	kShowEnglandCloth		= 32821,
	kShowEnglandFood		= 32822,
	kShowEnglandHistory		= 32823,
	kShowEnglandNature		= 32824,
	kShowEnglandPeople		= 32825,
	kShowEnglandPlaces		= 32826,
	kShowEnglandReligion	= 32827,

	kShowEgyptArt			= 32828,
	kShowEgyptCloth			= 32829,
	kShowEgyptFood			= 32830,
	kShowEgyptHistory		= 32831,
	kShowEgyptNature		= 32832,
	kShowEgyptPeople		= 32833,
	kShowEgyptPlaces		= 32834,
	kShowEgyptReligion		= 32835,

	kShowIndiaArt			= 32836,
	kShowIndiaCloth			= 32837,
	kShowIndiaFood			= 32838,
	kShowIndiaHistory		= 32839,
	kShowIndiaNature		= 32840,
	kShowIndiaPeople		= 32841,
	kShowIndiaPlaces		= 32842,
	kShowIndiaReligion		= 32843
};

enum {
	kShowGameWebPage			= 32844,
	kShowTechSupport			= 32778,
	kShowOnlineHints			= 32777,
	kShowWanderLustWebPage		= 32775,
	kShowHelp					= 32846,
	kShowHints					= 32847,

	kShowWinnnerPage			= 32779,
	kShowWanderlustInteractive	= 32849,
	kShowMGM					= 32848,
	kShowDiagnostics			= 32850,
	kShowAbout					= 57664
};

enum {
	kRecentSaveId		= 9,
	kRecentSavesOffset	= 400000
};

static const int kMaxSaves = 10;

static void menuCommandsCallback(int action, Common::U32String &, void *data) {
	PinkEngine *engine = (PinkEngine *)data;

	engine->executeMenuCommand(action);
}

struct SaveStateDescriptorTimeComparator {
	bool operator()(const SaveStateDescriptor &x, const SaveStateDescriptor &y) const {
		return x.getSaveDate() == y.getSaveDate() ? x.getSaveTime() > y.getSaveTime() : x.getSaveDate() > y.getSaveDate();
	}
};

SaveStateList PinkEngine::listSaves() const {
	Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
	Common::String pattern = getMetaEngine()->getSavegameFile(kSavegameFilePattern, _targetName.c_str());
	Common::StringArray filenames = saveFileMan->listSavefiles(pattern);

	SaveStateList saveList;
	for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
		// Obtain the last 2 digits of the filename, since they correspond to the save slot
		int slotNum = atoi(file->c_str() + file->size() - 2);
		Common::ScopedPtr<Common::InSaveFile> in(saveFileMan->openForLoading(*file));
		if (in) {
			SaveStateDescriptor desc;
			desc.setSaveSlot(slotNum);
			if (Pink::readSaveHeader(*in.get(), desc))
				saveList.push_back(desc);
		}
	}

	// Sort saves based on save time.
	Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorTimeComparator());
	return saveList;
}

void PinkEngine::initMenu() {
	_screen->getWndManager().setEngine(this);

	_menu = Graphics::MacMenu::createMenuFromPEexe(_exeResources, &_screen->getWndManager());
	if (getLanguage() == Common::HE_ISR) {
		_menu->setAlignment(Graphics::kTextAlignRight);
	}

	Graphics::MacMenuSubMenu *subMenu = _menu->getSubmenu(nullptr, 0);
	if (subMenu) {

		if (isPerilDemo()) {
			// From the first submenu ("Game"), disable the (zero indexed) item 5 ("Songs").
			// Use setEnabled() rather than removeMenuItem() since the latter removes the item
			// out of the list changing the index for the items that follow.
			// The effect is that "Songs" will be greyed out for the demo, since it's not available for it.
			// The original demo does not have the "Songs" item in the menu at all.
			_menu->setEnabled( _menu->getSubMenuItem(_menu->getMenuItem(0), 5), false);
		}

		SaveStateList saves = listSaves();
		if (!saves.empty()) {
			_menu->removeMenuItem(subMenu, kRecentSaveId);
			int maxSaves = saves.size() > kMaxSaves ? kMaxSaves : saves.size();
			for (int i = 0; i < maxSaves; ++i) {
				_menu->insertMenuItem(subMenu, Common::U32String::format("%i. %S", i + 1, saves[i].getDescription().u32_str()),
										kRecentSaveId + i, saves[i].getSaveSlot() + kRecentSavesOffset);
			}
		}
	}

	_menu->calcDimensions();
	_menu->setCommandsCallback(&menuCommandsCallback, this);
}

void PinkEngine::executeMenuCommand(uint id) {
	if (executePageChangeCommand(id))
		return;

	if (id >= kRecentSavesOffset) {
		int slotNum = id - kRecentSavesOffset;
		Common::Error loadError = loadGameState(slotNum);
		if (loadError.getCode() != Common::kNoError) {
			GUI::MessageDialog errorDialog(loadError.getDesc());
			errorDialog.runModal();
		}
		return;
	}

	switch (id) {
	case kNewGameAction: {
		initModule(_modules[0]->getName(), "", nullptr);
		break;
	}
	case kLoadSave:
		loadGameDialog();
		break;

	case kSaveAction:
	case kSaveAsAction:
		saveGameDialog();
		break;

	case kSoundSettingsAction:
	case kLastSavesAction:
	case kPauseAction:
	case kExitAction:
		openMainMenuDialog();
		break;

	case kSongsAction:
		initModule("Muzik", "", nullptr);
		break;

	case kShowPDAAction:
		_actor->loadPDA(kNavigatePage);
		break;

	// Cases kShowAustraliaArt - kShowIndiaReligion are handled in executePageChangeCommand()

	case kShowContent:
		_actor->loadPDA("TOC");
		break;
	case kShowGreece:
		_actor->loadPDA("GREOVER");
		break;
	case kShowIndonesia:
		_actor->loadPDA("INDOVER");
		break;
	case kShowIsrael:
		_actor->loadPDA("ISROVER");
		break;
	case kShowKenya:
		_actor->loadPDA("KENOVER");
		break;
	case kShowRussia:
		_actor->loadPDA("SIBOVER");
		break;

	case kShowGameWebPage:
		openLocalWebPage("PINK.HTM");
		break;
	case kShowTechSupport:
		openLocalWebPage("SUPPORT.HTM");
		break;
	case kShowWinnnerPage:
		openLocalWebPage("WINNER.HTM");
		break;
	case kShowWanderLustWebPage:
		openLocalWebPage("LUST.HTM");
		break;
	case kShowOnlineHints:
		openLocalWebPage("HINTS.HTM");
		break;

	default:
		{
			GUI::MessageDialog dialog(_("This menu item is not yet implemented"));
			dialog.runModal();
			warning("Unprocessed command id %d", id);
		}
		break;
	}
}

// Australia, Bhutan, China, Britain, Egypt, India
static const char *pageChangePrefixes[] = { "AUS", "BHU", "CHI", "BRI", "EGY", "IND" };
// Art, Cloth, Food, History, Nature, People, Places, Religion
static const char *pageChangeSuffixes[] = { "ART", "CLO", "FOO", "HIS", "NAT", "PEO", "PLA", "REL" };

bool PinkEngine::executePageChangeCommand(uint id) {
	if (id >= kShowAustraliaArt && id <= kShowIndiaReligion) {
		Common::String prefix = pageChangePrefixes[(id - kShowAustraliaArt) / 8];
		Common::String suffix = pageChangeSuffixes[(id - kShowAustraliaArt) % 8];
		_actor->loadPDA(prefix + suffix);
		return true;
	}

	return false;
}

void PinkEngine::openLocalWebPage(const Common::String &pageName) const {
	Common::FSNode gameFolder = Common::FSNode(ConfMan.getPath("path"));
	Common::FSNode filePath = gameFolder.getChild("INSTALL").getChild(pageName);
	if (filePath.exists()) {
		Common::String fullUrl = Common::String::format("file:///%s", filePath.getPath().toString('/').c_str());
		_system->openUrl(fullUrl);
	}
}

} // End of namespace Pink
