/* 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 "common/config-manager.h"
#include "graphics/scaler.h"
#include "mads/mads.h"
#include "mads/game.h"
#include "mads/screen.h"
#include "mads/msurface.h"
#include "mads/nebular/game_nebular.h"
#include "mads/nebular/dialogs_nebular.h"
#include "mads/nebular/globals_nebular.h"
#include "mads/nebular/nebular_scenes.h"

namespace MADS {

namespace Nebular {

GameNebular::GameNebular(MADSEngine *vm)
	: Game(vm) {
	_surface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
	_storyMode = STORYMODE_NAUGHTY;
	_difficulty = DIFFICULTY_HARD;
}

ProtectionResult GameNebular::checkCopyProtection() {
	/*
	// DEBUG: Flag copy protection failure
	_globals[kCopyProtectFailed] = -1;

	if (!ConfMan.getBool("copy_protection"))
	return true;

	* DEBUG: Disabled for now
	CopyProtectionDialog *dlg = new CopyProtectionDialog(_vm, false);
	dlg->show();
	delete dlg;
	*/
	return PROTECTION_SUCCEED;
}

void GameNebular::startGame() {
	// Show the main menu
	// TODO: Show the main menu here

	// Check copy protection
	ProtectionResult protectionResult = checkCopyProtection();
	switch (protectionResult) {
	case PROTECTION_FAIL:
		// Copy protection failed
		_scene._nextSceneId = 804;
		initializeGlobals();
		_globals[kCopyProtectFailed] = true;
		return;
	case PROTECTION_ESCAPE:
		// User escaped out of copy protection dialog
		_vm->quitGame();
		return;
	default:
		// Copy protection check succeeded
		break;
	}

	initSection(_sectionNumber);
	_statusFlag = true;

	_vm->_dialogs->_pendingDialog = DIALOG_DIFFICULTY;
	_vm->_dialogs->showDialog();
	_vm->_dialogs->_pendingDialog = DIALOG_NONE;

	_priorSectionNumber = 0;
	_priorSectionNumber = -1;
	_scene._priorSceneId = 0;
	_scene._currentSceneId = -1;
	_scene._nextSceneId = 101;

	initializeGlobals();
}

void GameNebular::initializeGlobals() {
	int count, count2;
	int bad;

	_globals.reset();
	_globals[kTalkInanimateCount] = 8;

	/* Section #1 variables */
	_globals[kNeedToStandUp] = true;
	_globals[kTurkeyExploded] = false;
	_globals[kMedicineCabinetOpen] = false;
	_globals[kMedicineCabinetVirgin] = true;
	_globals[kWatchedViewScreen] = false;
	_globals[kHoovicAlive] = true;
	_globals[kWaterInAPuddle] = false;

	_globals[kFishIn105] = true;
	_globals[kFishIn107] = true;
	_globals[kFishIn108] = true;

	/* Section #2 variables */
	_globals[kLadderBroken] = false;
	_globals[kBone202Status] = 0;
	_globals[kRhotundaStatus] = RHOTUNDA_HUNGRY;
	_globals[kMonkeyStatus] = MONKEY_AMBUSH_READY;
	_globals[kMeteorologistStatus] = METEOROLOGIST_PRESENT;
	_globals[kMeteorologistEverSeen] = false;
	_globals[kMeteorologistWatch] = METEOROLOGIST_NORMAL;
	_globals[kTeleporterCommand] = TELEPORTER_NONE;
	_globals[kTeleporterUnderstood] = false;
	_globals[kTwinklesStatus] = TWINKLES_AT_HOME;
	_globals[kTwinklesApproached] = 0;

	/* Section #3 variables */
	_globals[kAfterHavoc] = false;
	_globals[kKickedIn391Grate] = false;

	/* Section #4 variables */
	_globals[kBadFirstIngredient] = -1;
	_objects[OBJ_CHARGE_CASES].setQuality(EXPLOSIVES_INSIDE, 0);
	_globals[kHasPurchased] = false;
	_globals[kBeenThruHelgaScene] = false;
	_globals[kNextIngredient] = 0;
	_globals[kHasSaidTimer] = false;
	_globals[kHasSaidBinocs] = false;
	_globals[kBottleDisplayed] = false;
	_globals[kHasBeenScanned] = false;
	_globals[kSomeoneHasExploded] = false;

	// Generate a random ingredient list
	for (count = 0; count < 4; ++count) {
		do {
			_globals[kIngredientList + count] = _vm->getRandomNumber(3);
			bad = false;
			for (count2 = 0; count2 < count; ++count2) {
				if (_globals[kIngredientList + count] == _globals[kIngredientList + count2]) {
					bad = true;
				}
			}
		} while (bad);
	}

	// Generate random ingredient quantities
	for (count = 0; count < 4; ++count) {
		do {
			_globals[kIngredientQuantity + count] = _vm->getRandomNumber(3);
			bad = false;
			for (count2 = 0; count2 < count; ++count2) {
				if (_globals[kIngredientQuantity + count] == _globals[kIngredientQuantity + count2]) {
					bad = true;
				}
			}
		} while (bad);
	}


	/* Section #5 variables */
	_globals[kHoverCarLocation] = 501;
	_globals[kHoverCarDestination] = -1;
	_globals[kCityFlooded] = false;
	_globals[kBoatRaised] = true;
	_globals[kLaserHoleIsThere] = false;
	_globals[kLineStatus] = LINE_NOT_DROPPED;


	/* Section #6 variables */
	_globals[kHasTalkedToHermit] = false;
	_globals[kHandsetCellStatus] = FIRST_TIME_PHONE_CELLS;
	_globals[kTimebombStatus] = TIMEBOMB_DEACTIVATED;
	_globals[kWarnedFloodCity] = false;
	_globals._timebombClock = 0;
	_globals._timebombTimer = 0;


	/* Section #7 variables */
	_globals[kBottleStatus] = BOTTLE_EMPTY;
	_globals[kBoatStatus] = BOAT_UNFLOODED;


	/* Section #8 variables */
	_globals[kWindowFixed] = false;
	_globals[kInSpace] = false;
	_globals[kReturnFromCut] = false;
	_globals[kBeamIsUp] = false;
	_globals[kForceBeamDown] = false;
	_globals[kCameFromCut] = false;
	_globals[kDontRepeat] = false;
	_globals[kHoppyDead] = false;
	_globals[kHasWatchedAntigrav] = false;
	_globals[kRemoteSequenceRan] = false;
	_globals[kRemoteOnGround] = false;
	_globals[kFromCockpit] = false;
	_globals[kExitShip] = false;
	_globals[kBetweenRooms] = false;
	_globals[kTopButtonPushed] = false;
	_globals[kShieldModInstalled] = false;
	_globals[kTargetModInstalled] = false;
	_globals[kUpBecauseOfRemote] = false;


	/* Set up the game's teleporters */
	_globals[kTeleporterRoom] = 201;
	_globals[kTeleporterRoom + 1] = 301;
	_globals[kTeleporterRoom + 2] = 413;
	_globals[kTeleporterRoom + 3] = 706;
	_globals[kTeleporterRoom + 4] = 801;
	_globals[kTeleporterRoom + 5] = 551;
	_globals[kTeleporterRoom + 6] = 752;
	_globals[kTeleporterRoom + 7] = 0;
	_globals[kTeleporterRoom + 8] = 0;
	_globals[kTeleporterRoom + 9] = 0;

	for (count = 0; count < TELEPORTER_COUNT; ++count) {
		do {
			_globals[kTeleporterCode + count] = _vm->getRandomNumber(9999);
			bad = false;
			for (count2 = 0; count2 < count; ++count2) {
				if (_globals[kTeleporterCode + count] == _globals[kTeleporterCode + count2]) {
					bad = true;
				}
			}
		} while (bad);
	}

	// Final setup based on selected difficulty level
	switch (_difficulty) {
	case DIFFICULTY_HARD:
		_objects.setRoom(OBJ_PLANT_STALK, NOWHERE);
		_objects.setRoom(OBJ_PENLIGHT, NOWHERE);

		_globals[kLeavesStatus] = LEAVES_ON_TRAP;
		break;

	case DIFFICULTY_MEDIUM:
		_objects.setRoom(OBJ_PLANT_STALK, NOWHERE);

		_globals[kLeavesStatus] = LEAVES_ON_GROUND;
		_globals[kDurafailRecharged] = 1;
		_globals[kPenlightCellStatus] = FIRST_TIME_CHARGED_DURAFAIL;
		break;

	case DIFFICULTY_EASY:
		_objects.setRoom(OBJ_BLOWGUN, NOWHERE);
		_objects.setRoom(OBJ_NOTE, NOWHERE);

		_globals[kLeavesStatus] = LEAVES_ON_GROUND;
		_globals[kPenlightCellStatus] = FIRST_TIME_UNCHARGED_DURAFAIL;
		_globals[kDurafailRecharged] = 0;
		break;
	}

	_player._facing = FACING_NORTH;
	_player._turnToFacing = FACING_NORTH;

	Player::preloadSequences("RXM", 1);
	Player::preloadSequences("ROX", 1);
}

void GameNebular::setSectionHandler() {
	delete _sectionHandler;

	switch (_sectionNumber) {
	case 1:
		_sectionHandler = new Section1Handler(_vm);
		break;
	case 2:
		_sectionHandler = new Section2Handler(_vm);
		break;
	case 3:
		_sectionHandler = new Section3Handler(_vm);
		break;
	case 4:
		_sectionHandler = new Section4Handler(_vm);
		break;
	case 5:
		_sectionHandler = new Section5Handler(_vm);
		break;
	case 6:
		_sectionHandler = new Section6Handler(_vm);
		break;
	case 7:
		_sectionHandler = new Section7Handler(_vm);
		break;
	case 8:
		_sectionHandler = new Section8Handler(_vm);
		break;
	default:
		break;
	}
}

void GameNebular::checkShowDialog() {
	if (_vm->_dialogs->_pendingDialog && _player._stepEnabled && !_globals[kCopyProtectFailed]) {
		_player.releasePlayerSprites();

		// Make a thumbnail in case it's needed for making a savegame
		_vm->_game->createThumbnail();

		// Show the dialog
		_vm->_dialogs->showDialog();
		_vm->_dialogs->_pendingDialog = DIALOG_NONE;
	}
}

void GameNebular::showRecipe() {
	Dialogs &dialogs = *_vm->_dialogs;
	int count;

	for (count = 0; count < 4; count++) {
		switch(_globals[kIngredientQuantity + count]) {
		case 0:
			dialogs._indexList[count] = NOUN_DROP;
			break;
		case 1:
			dialogs._indexList[count] = NOUN_DOLLOP;
			break;
		case 2:
			dialogs._indexList[count] = NOUN_DASH;
			break;
		case 3:
			dialogs._indexList[count] = NOUN_SPLASH;
			break;
		default:
			break;
		}
	}

	for (count = 0; count < 4; count++) {
		switch(_globals[kIngredientList + count]) {
		case 0:
			dialogs._indexList[count + 4] = NOUN_ALCOHOL;
			break;
		case 1:
			dialogs._indexList[count + 4] = NOUN_LECITHIN;
			break;
		case 2:
			dialogs._indexList[count + 4] = NOUN_PETROX;
			break;
		case 3:
			dialogs._indexList[count + 4] = NOUN_FORMALDEHYDE;
			break;
		default:
			break;
		}
	}

	_vm->_dialogs->show(401);
}

void GameNebular::doObjectAction() {
	Scene &scene = _scene;
	MADSAction &action = _scene._action;
	Dialogs &dialogs = *_vm->_dialogs;
	int id;

	if (action.isAction(VERB_SMELL) && scene._currentSceneId > 103 && scene._currentSceneId < 111) {
		dialogs.show(440);
	} else if (action.isAction(VERB_EAT) && scene._currentSceneId > 103 && scene._currentSceneId < 111) {
		dialogs.show(441);
	} else if (action.isAction(VERB_SMELL, NOUN_BURGER)) {
		dialogs.show(442);
	} else if (action.isAction(VERB_EAT, NOUN_BURGER)) {
		dialogs.show(443);
	} else if (action.isAction(VERB_SMELL, NOUN_STUFFED_FISH)) {
		dialogs.show(444);
	} else if (action.isAction(VERB_EAT, NOUN_STUFFED_FISH)) {
		dialogs.show(445);
	} else if (action.isAction(VERB_WEAR, NOUN_REBREATHER)) {
		dialogs.show(scene._currentSceneId > 103 && scene._currentSceneId < 111 ? 446 : 447);
	} else if (action.isAction(VERB_SET, NOUN_TIMER_MODULE)) {
		dialogs.show(448);
	} else if (action.isAction(VERB_NIBBLE_ON, NOUN_BIG_LEAVES)) {
		dialogs.show(449);
	} else if (action.isAction(VERB_LICK, NOUN_POISON_DARTS)) {
		dialogs.show(450);
	} else if (action.isAction(VERB_EAT, NOUN_TWINKIFRUIT)) {
		_objects.setRoom(OBJ_TWINKIFRUIT, NOWHERE);
		dialogs.show(451);
	} else if (action.isAction(VERB_GORGE_ON, NOUN_TWINKIFRUIT)) {
		_objects.setRoom(OBJ_TWINKIFRUIT, NOWHERE);
		dialogs.show(452);
	} else if (action.isAction(VERB_GNAW_ON)) {
		dialogs.show(453);
	} else if (action.isAction(VERB_MASSAGE, NOUN_AUDIO_TAPE)) {
		dialogs.show(454);
	} else if (action.isAction(VERB_MANGLE, NOUN_CREDIT_CHIP)) {
		dialogs.show(455);
	} else if (action.isAction(VERB_FONDLE, NOUN_CHARGE_CASES)) {
		dialogs.show(456);
	} else if (action.isAction(VERB_RUB, NOUN_BOMB)) {
		dialogs.show(457);
	} else if (action.isAction(VERB_SET, NOUN_TIMEBOMB)) {
		dialogs.show(458);
	} else if (action.isAction(VERB_GUZZLE, NOUN_ALIEN_LIQUOR)) {
		dialogs.show(459);
	} else if (action.isAction(VERB_SMASH, NOUN_TARGET_MODULE)) {
		dialogs.show(460);
	} else if (action.isAction(VERB_JUGGLE)) {
		dialogs.show(461);
	} else if (action.isAction(VERB_APPLY, NOUN_POLYCEMENT)) {
		dialogs.show(462);
	} else if (action.isAction(VERB_SNIFF, NOUN_POLYCEMENT)) {
		dialogs.show(465);
	} else if (action.isAction(VERB_TIE, NOUN_FISHING_LINE)) {
		dialogs.show(463);
	} else if (action.isAction(VERB_ATTACH, NOUN_FISHING_LINE)) {
		dialogs.show(463);
	} else if (action.isAction(VERB_UNLOCK)) {
		dialogs.show(464);
	} else if (action.isAction(VERB_REFLECT)) {
		dialogs.show(466);
	} 	else if (action.isAction(VERB_GAZE_INTO, NOUN_REARVIEW_MIRROR)) {
		dialogs.show(467);
	} else if (action.isAction(VERB_EAT, NOUN_CHICKEN_BOMB)) {
		dialogs.show(469);
	} else if (action.isAction(VERB_BREAK, NOUN_VASE)) {
		dialogs.show(471);
	} else if (action.isAction(VERB_SHAKE_HANDS, NOUN_GUARDS_ARM2)) {
		dialogs.show(472);
	} else if (action.isAction(VERB_READ, NOUN_LOG)) {
		dialogs.show(473);
	} else if (action.isAction(VERB_RUB, NOUN_BOMBS)) {
		dialogs.show(474);
	} else if (action.isAction(VERB_DRINK, NOUN_FORMALDEHYDE)) {
		dialogs.show(475);
	} else if (action.isAction(VERB_DRINK, NOUN_PETROX)) {
		dialogs.show(476);
	} else if (action.isAction(VERB_DRINK, NOUN_LECITHIN)) {
		dialogs.show(477);
	} else if (action.isAction(VERB_PUT, NOUN_POISON_DARTS, NOUN_PLANT_STALK) && _objects.isInInventory(OBJ_POISON_DARTS)
			&& _objects.isInInventory(OBJ_PLANT_STALK)) {
		_objects.addToInventory(OBJ_BLOWGUN);
		_objects.setRoom(OBJ_PLANT_STALK, NOWHERE);
		_globals[kBlowgunStatus] = 0;
		dialogs.showItem(OBJ_BLOWGUN, 809);
	} else if (action.isAction(VERB_PUT, NOUN_POISON_DARTS, NOUN_BLOWGUN) && _objects.isInInventory(OBJ_POISON_DARTS)
			&& _objects.isInInventory(OBJ_BLOWGUN)) {
		dialogs.show(433);
	} else if (action.isAction(VERB_DEFACE) && action.isAction(VERB_FOLD) && action.isAction(VERB_MUTILATE)) {
		dialogs.show(434);
	} else if (action.isAction(VERB_SPINDLE)) {
		dialogs.show(479);
	} else if ((action.isAction(VERB_READ) || action.isAction(VERB_LOOK_AT) || action.isAction(VERB_LOOK)) &&
			action.isObject(NOUN_NOTE) && _objects.isInInventory(OBJ_NOTE)) {
		_objects.setRoom(OBJ_NOTE, NOWHERE);
		_objects.addToInventory(OBJ_COMBINATION);
		dialogs.showItem(OBJ_COMBINATION, 851);
	} else if ((action.isAction(VERB_LOOK) || action.isAction(VERB_READ)) &&
			((id = _objects.getIdFromDesc(action._activeAction._objectNameId)) > 0 ||
			(action._activeAction._indirectObjectId > 0 &&
			(id = _objects.getIdFromDesc(action._activeAction._indirectObjectId)))) &&
			_objects.isInInventory(id)) {
		if (id == OBJ_REPAIR_LIST) {
			dialogs._indexList[0] = _globals[kTeleporterCode + 7];
			dialogs._indexList[1] = _globals[kTeleporterCode + 8];
			dialogs._indexList[2] = _globals[kTeleporterCode + 6];
			dialogs._indexList[3] = _globals[kTeleporterCode + 9];
			dialogs._indexList[4] = _globals[kTeleporterCode + 0];
			dialogs._indexList[5] = _globals[kTeleporterCode + 1];
			dialogs._indexList[6] = _globals[kTeleporterCode + 4];
			dialogs._indexList[7] = _globals[kTeleporterCode + 5];
			dialogs._indexList[8] = _globals[kTeleporterCode + 2];

			dialogs.showItem(id, 402);
		} else {
			int messageId = 800 + id;
			if ((id == OBJ_CHARGE_CASES) && _objects[OBJ_CHARGE_CASES].getQuality(3) != 0) {
				messageId = 860;
			}

			if (id == OBJ_TAPE_PLAYER && _objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER)
				messageId = 867;

			if (id == 32 && _objects[OBJ_FISHING_LINE]._roomNumber == 3)
				messageId = 862;

			if (id == OBJ_BOTTLE && _globals[kBottleStatus] != 0)
				messageId = 862 + _globals[kBottleStatus];

			if (id == OBJ_PHONE_HANDSET && _globals[kHandsetCellStatus])
				messageId = 861;

			dialogs.showItem(id, messageId);
		}
	} else if (action.isAction(VERB_PUT, NOUN_BURGER, NOUN_DEAD_FISH)) {
		if (_objects.isInInventory(OBJ_BURGER) || _objects.isInInventory(OBJ_DEAD_FISH)) {
			_objects.removeFromInventory(OBJ_DEAD_FISH, PLAYER_INVENTORY);
			_objects.removeFromInventory(OBJ_BURGER, PLAYER_INVENTORY);
			_objects.addToInventory(OBJ_STUFFED_FISH);
			dialogs.showItem(OBJ_STUFFED_FISH, 803);
		}
	} else if (action.isAction(VERB_PUT, NOUN_AUDIO_TAPE, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_AUDIO_TAPE) &&
			_objects.isInInventory(OBJ_TAPE_PLAYER)) {
		_objects.setRoom(OBJ_AUDIO_TAPE, OBJ_TAPE_PLAYER);
	} else if (action.isAction(VERB_ACTIVATE, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_TAPE_PLAYER)) {
		if (_objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER) {
			showRecipe();
		} else {
			dialogs.show(406);
		}
	} else if (action.isAction(VERB_EJECT, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_TAPE_PLAYER)) {
		if (_objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER) {
			_objects.addToInventory(OBJ_AUDIO_TAPE);
		} else {
			dialogs.show(407);
		}
	} else if (action.isAction(VERB_DISASSEMBLE, NOUN_TAPE_PLAYER)) {
		dialogs.show(408);
	} else if (action.isAction(VERB_ACTIVATE, NOUN_REMOTE)) {
		dialogs.show(_globals[kTopButtonPushed] ? 502 : 501);
	} else if ((action.isAction(VERB_ATTACH, NOUN_DETONATORS, NOUN_CHARGE_CASES) || action.isAction(VERB_PUT, NOUN_DETONATORS, NOUN_CHARGE_CASES)) &&
			_objects.isInInventory(OBJ_DETONATORS) && _objects.isInInventory(OBJ_CHARGE_CASES)) {
		if (_objects[OBJ_CHARGE_CASES].getQuality(3)) {
			_objects.setRoom(OBJ_CHARGE_CASES, NOWHERE);
			_objects.setRoom(OBJ_DETONATORS, NOWHERE);
			_objects.addToInventory(OBJ_BOMBS);
			dialogs.showItem(OBJ_BOMBS, 403);
		} else {
			dialogs.show(405);
		}
	} else if (action.isAction(VERB_ATTACH, NOUN_DETONATORS)) {
		dialogs.show(470);
	} else if ((action.isAction(VERB_ATTACH, NOUN_TIMER_MODULE, NOUN_BOMBS) || action.isAction(VERB_PUT, NOUN_TIMER_MODULE, NOUN_BOMBS) || action.isAction(VERB_ATTACH, NOUN_TIMER_MODULE, NOUN_BOMB)
			|| action.isAction(VERB_PUT, NOUN_TIMER_MODULE, NOUN_BOMB)) && _objects.isInInventory(OBJ_TIMER_MODULE) && (
			_objects.isInInventory(OBJ_BOMBS) || _objects.isInInventory(OBJ_BOMB))) {
		if (_objects.isInInventory(OBJ_BOMBS)) {
			_objects.setRoom(OBJ_BOMBS, NOWHERE);
			_objects.addToInventory(OBJ_BOMB);
		} else {
			_objects.setRoom(OBJ_BOMB, NOWHERE);
		}

		_objects.setRoom(OBJ_TIMER_MODULE, NOWHERE);
		_objects.addToInventory(OBJ_TIMEBOMB);
		dialogs.showItem(OBJ_TIMEBOMB, 404);
	} else if (action.isAction(VERB_FONDLE, NOUN_PLANT_STALK)) {
		dialogs.show(410);
	} else if (action.isAction(VERB_EMPTY, NOUN_BOTTLE)) {
		_globals[kBottleStatus] = 0;
		dialogs.show(432);
	} else if (action.isAction(VERB_DISASSEMBLE, NOUN_FISHING_ROD)) {
		if (_objects[OBJ_FISHING_LINE]._roomNumber == 3) {
			_objects.addToInventory(OBJ_FISHING_LINE);
			dialogs.showItem(OBJ_FISHING_LINE, 409);
		} else {
			dialogs.show(428);
		}
	} else if (action.isAction(VERB_DISASSEMBLE, NOUN_PENLIGHT)) {
		switch (_globals[kPenlightCellStatus]) {
		case 1:
		case 2:
			_objects.addToInventory(OBJ_DURAFAIL_CELLS);
			dialogs.showItem(OBJ_DURAFAIL_CELLS, 412);
			break;
		case 3:
			_objects.addToInventory(OBJ_PHONE_CELLS);
			dialogs.showItem(OBJ_DURAFAIL_CELLS, 413);
			break;
		case 5:
			_objects.addToInventory(OBJ_DURAFAIL_CELLS);
			dialogs.showItem(OBJ_DURAFAIL_CELLS, 411);
			break;
		case 6:
			_objects.addToInventory(OBJ_DURAFAIL_CELLS);
			dialogs.showItem(OBJ_DURAFAIL_CELLS, 429);
			break;
		default:
			dialogs.show(478);
			break;
		}
	} else if (action.isAction(VERB_DISASSEMBLE, NOUN_PHONE_HANDSET)) {
		switch (_globals[kHandsetCellStatus]) {
		case 1:
			_objects.addToInventory(OBJ_DURAFAIL_CELLS);
			dialogs.showItem(OBJ_DURAFAIL_CELLS,
				_difficulty != DIFFICULTY_HARD || _globals[kDurafailRecharged] ? 415 : 414);
			_globals[kDurafailRecharged] = true;
			break;
		case 2:
			_objects.addToInventory(OBJ_DURAFAIL_CELLS);
			if (_difficulty == DIFFICULTY_HARD) {
				dialogs.showItem(OBJ_DURAFAIL_CELLS, 416);
			} 
			_globals[kHandsetCellStatus] = 0;
			break;
		case 3:
			_objects.addToInventory(OBJ_PHONE_CELLS);
			dialogs.showItem(OBJ_PHONE_CELLS, 418);
			break;
		case 4:
			_objects.addToInventory(OBJ_PHONE_CELLS);
			dialogs.showItem(OBJ_PHONE_CELLS, 417);
			_globals[kHandsetCellStatus] = 0;
			break;
		default:
			dialogs.show(478);
			break;
		}
	} else if (action.isAction(VERB_PUT, NOUN_PHONE_CELLS, NOUN_PENLIGHT)) {
		if (_globals[kPenlightCellStatus] == 0) {
			_globals[kPenlightCellStatus] = 3;
			_objects.setRoom(OBJ_PHONE_CELLS, NOWHERE);
			dialogs.show(419);
		} else {
			dialogs.show(420);
		}
	} else if (action.isAction(VERB_PUT, NOUN_PHONE_CELLS, NOUN_PHONE_HANDSET)) {
		if (_globals[kHandsetCellStatus] == 0) {
			_globals[kHandsetCellStatus] = 3;
			_objects.setRoom(OBJ_PHONE_CELLS, NOWHERE);
			dialogs.show(421);
		} else {
			dialogs.show(422);
		}
	} else if (action.isAction(VERB_PUT, NOUN_DURAFAIL_CELLS, NOUN_PENLIGHT)) {
		if (_globals[kPenlightCellStatus]) {
			dialogs.show(424);
		} else {
			_objects.setRoom(OBJ_DURAFAIL_CELLS, NOWHERE);
			_globals[kPenlightCellStatus] = _difficulty != DIFFICULTY_HARD || _globals[kDurafailRecharged] ? 1 : 2;
			dialogs.show(423);
		}
	} else if (action.isAction(VERB_PUT, NOUN_DURAFAIL_CELLS, NOUN_PHONE_HANDSET)) {
		if (_globals[kHandsetCellStatus]) {
			dialogs.show(426);
		} else {
			_objects.setRoom(OBJ_DURAFAIL_CELLS, NOWHERE);
			_globals[kHandsetCellStatus] = _difficulty != DIFFICULTY_HARD || _globals[kHandsetCellStatus] ? 1 : 2;
			dialogs.show(425);
		}
	} else if (action.isAction(VERB_SET, NOUN_TIMEBOMB)) {
		dialogs.show(427);
	} else if (action.isAction(VERB_PUT, NOUN_BOMB, NOUN_CHICKEN) || action.isAction(VERB_PUT, NOUN_BOMBS, NOUN_CHICKEN)) {
		_objects.setRoom(OBJ_CHICKEN, NOWHERE);
		if (_objects.isInInventory(OBJ_BOMBS)) {
			_objects.setRoom(OBJ_BOMBS, NOWHERE);
			_objects.addToInventory(OBJ_BOMB);
		} else {
			_objects.setRoom(OBJ_BOMB, NOWHERE);
		}

		_objects.addToInventory(OBJ_CHICKEN_BOMB);
		dialogs.showItem(OBJ_CHICKEN_BOMB, 430);
	} else {
		return;
	}

	action._inProgress = false;
}

void GameNebular::unhandledAction() {
	int randVal = _vm->getRandomNumber(1, 1000);
	MADSAction &action = _scene._action;

	if (action.isAction(VERB_THROW, NOUN_BOMB) || action.isAction(VERB_THROW, NOUN_BOMBS)
	|| action.isAction(VERB_THROW, NOUN_TIMEBOMB) || action.isAction(VERB_THROW, NOUN_CHICKEN_BOMB))
		_vm->_dialogs->show(42);
	else if (action.isAction(VERB_DISASSEMBLE))
		_vm->_dialogs->show(435);
	else if ((action.isAction(VERB_EAT, NOUN_DEAD_FISH) || action.isAction(VERB_EAT, NOUN_STUFFED_FISH)) && _vm->_game->_objects.isInInventory(_vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId)))
		_vm->_dialogs->show(12);
	else if ((action.isAction(VERB_SMELL, NOUN_DEAD_FISH) || action.isAction(VERB_SMELL, NOUN_STUFFED_FISH)) && _vm->_game->_objects.isInInventory(_vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId)))
		_vm->_dialogs->show(13);
	else if (action.isAction(VERB_EAT, NOUN_CHICKEN) && _vm->_game->_objects.isInInventory(OBJ_CHICKEN))
		_vm->_dialogs->show(912);
	else if ((action.isAction(VERB_SHOOT) || action.isAction(VERB_HOSE_DOWN)) && action.isObject(NOUN_BLOWGUN)) {
		if ((_scene._currentSceneId >= 104) && (_scene._currentSceneId <= 111))
			_vm->_dialogs->show(38);
		else if (action.isObject(NOUN_PIRANHA))
			_vm->_dialogs->show(41);
		else if (action.isObject(NOUN_CHICKEN) || action.isObject(NOUN_VULTURE) || action.isObject(NOUN_SPIDER)
				|| action.isObject(NOUN_YELLOW_BIRD) || action.isObject(NOUN_SWOOPING_CREATURE) || action.isObject(NOUN_CAPTIVE_CREATURE)) {
			_vm->_dialogs->show(40);
		} else
			_vm->_dialogs->show(39);
	} else if (action.isAction(VERB_TALKTO)) {
		_globals[kTalkInanimateCount] = (_globals[kTalkInanimateCount] + 1) % 16;
		if (!_globals[kTalkInanimateCount]) {
			_vm->_dialogs->show(2);
		} else {
			Common::String tmpMsg = "\"Greetings, ";
			tmpMsg += _vm->_game->_scene.getVocab(action._activeAction._objectNameId);
			tmpMsg += "!\"";
			_scene._kernelMessages.reset();
			_scene._kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, tmpMsg);
		}
	} else if (action.isAction(VERB_GIVE, NOUN_DOOR, NOUN_CEILING) || action.isAction(VERB_CLOSE, NOUN_CHAIR))
		_vm->_dialogs->show(3);
	else if (action.isAction(VERB_THROW)) {
		int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId);
		if (objId < 0)
			_vm->_dialogs->show(4);
		else if (_vm->_game->_objects[objId]._roomNumber != 2)
			_vm->_dialogs->show(5);
		else
			_vm->_dialogs->show(6);
	} else if (action.isAction(VERB_LOOK)) {
		if (action.isObject(NOUN_BINOCULARS) && (action._activeAction._indirectObjectId > 0))
			_vm->_dialogs->show(10);
		else if (randVal < 600)
			_vm->_dialogs->show(7);
		else
			_vm->_dialogs->show(21);
	} else if (action.isAction(VERB_TAKE)) {
		int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId);
		if (_vm->_game->_objects.isInInventory(objId))
			_vm->_dialogs->show(16);
		else if (randVal <= 333)
			_vm->_dialogs->show(8);
		else if (randVal <= 666)
			_vm->_dialogs->show(22);
		else
			_vm->_dialogs->show(23);
	} else if (action.isAction(VERB_CLOSE)) {
		if (randVal <= 333)
			_vm->_dialogs->show(9);
		else
			_vm->_dialogs->show(33);
	} else if (action.isAction(VERB_OPEN)) {
		if (randVal <= 500)
			_vm->_dialogs->show(30);
		else if (randVal <= 750)
			_vm->_dialogs->show(31);
		else
			_vm->_dialogs->show(32);
	} else if (action.isAction(VERB_PULL))
		_vm->_dialogs->show(18);
	else if (action.isAction(VERB_PUSH)) {
		if (randVal < 750)
			_vm->_dialogs->show(19);
		else
			_vm->_dialogs->show(20);
	} else if (action.isAction(VERB_PUT)) {
		int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId);
		if (_vm->_game->_objects.isInInventory(objId))
			_vm->_dialogs->show(25);
		else
			_vm->_dialogs->show(24);
	} else if (action.isAction(VERB_GIVE)) {
		int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId);
		if (!_vm->_game->_objects.isInInventory(objId))
			_vm->_dialogs->show(26);
		else if (randVal <= 500)
			_vm->_dialogs->show(28);
		else
			_vm->_dialogs->show(29);
	} else if (!action.isAction(VERB_WALKTO) && !action.isAction(VERB_WALK_ACROSS) && !action.isAction(VERB_WALK_TOWARDS) && !action.isAction(VERB_WALK_DOWN)
			&& !action.isAction(VERB_SWIM_TO) && !action.isAction(VERB_SWIM_ACROSS) && !action.isAction(VERB_SWIM_INTO) && !action.isAction(VERB_SWIM_THROUGH)
			&& !action.isAction(VERB_SWIM_UNDER)) {
		if (randVal <= 100)
			_vm->_dialogs->show(36);
		else if (randVal <= 200)
			_vm->_dialogs->show(1);
		else if (randVal <= 475)
			_vm->_dialogs->show(34);
		else if (randVal <= 750)
			_vm->_dialogs->show(35);
		else
			_vm->_dialogs->show(37);
	}
}

void GameNebular::step() {
	if (_player._visible && _player._stepEnabled && !_player._moving &&
		(_player._facing == _player._turnToFacing)) {
		if (_scene._frameStartTime >= *((uint32 *)&_globals[kWalkerTiming])) {
			if (!_player._stopWalkerIndex) {
				int randomVal = _vm->getRandomNumber(29999);;
				if (_globals[kSexOfRex] == REX_MALE) {
					switch (_player._facing) {
					case FACING_SOUTHWEST:
					case FACING_SOUTHEAST:
					case FACING_NORTHWEST:
					case FACING_NORTHEAST:
						if (randomVal < 200) {
							_player.addWalker(-1, 0);
							_player.addWalker(1, 0);
						}
						break;

					case FACING_WEST:
					case FACING_EAST:
						if (randomVal < 500) {
							for (int count = 0; count < 10; ++count) {
								_player.addWalker(1, 0);
							}
						}
						break;

					case FACING_SOUTH:
						if (randomVal < 500) {
							for (int count = 0; count < 10; ++count) {
								_player.addWalker((randomVal < 250) ? 1 : 2, 0);
							}
						} else if (randomVal < 750) {
							for (int count = 0; count < 5; ++count) {
								_player.addWalker(1, 0);
							}

							_player.addWalker(0, 0);
							_player.addWalker(0, 0);

							for (int count = 0; count < 5; ++count) {
								_player.addWalker(2, 0);
							}
						}
						break;

					default:
						break;
					}
				}
			}

			*((uint32 *)&_globals[kWalkerTiming]) += 6;
		}
	}

	// Below is countdown to set the timebomb off in room 604
	if (_globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) {
		int diff = _scene._frameStartTime - *((uint32 *)&_globals[kTimebombClock]);
		if ((diff >= 0) && (diff <= 60)) {
			*((uint32 *)&_globals[kTimebombTimer]) += diff;
		} else {
			++*((uint32 *)&_globals[kTimebombTimer]);
		}
		*((uint32 *)&_globals[kTimebombClock]) = _scene._frameStartTime;
	}
}

void GameNebular::synchronize(Common::Serializer &s, bool phase1) {
	Game::synchronize(s, phase1);

	if (phase1) {
		_globals.synchronize(s);
		s.syncAsByte(_storyMode);
		s.syncAsByte(_difficulty);
	}
}

} // End of namespace Nebular

} // End of namespace MADS
