/* 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/>.
 *
 * Copyright 2020 Google
 *
 */
#include "hadesch/hadesch.h"
#include "hadesch/video.h"
#include "hadesch/rooms/monster.h"

namespace Hadesch {
enum {
	kBackgroundZ = 10000,
	kCyclopsZ = 500,
	kZeusLightZ = 500,
	kTyphoonZ = 500
};

static const char *kZeusLight = "V7100BJ0";
static const int kLightningCutoff = kVideoWidth / 2;

TranscribedSound revitalisedSound() {
	return g_vm->getRnd().getRandomBit()
		? TranscribedSound::make("v7150wd0", "Your branch of life is revitalized")
		: TranscribedSound::make("v7150we0", "You're back to full strength");
}

class MonsterHandler : public Handler {
public:
	MonsterHandler() {
		_playingShootingSound = false;
		_countOfIntroLightning = 0;
		_battleground = Common::SharedPtr<Battleground>(new Battleground());
		_typhoon = Common::SharedPtr<Typhoon>(new Typhoon(_battleground));
		_cyclops = Common::SharedPtr<Cyclops>(new Cyclops(_battleground));
		_illusion = Common::SharedPtr<Illusion>(new Illusion(_battleground));
	}

	void handleClick(const Common::String &name) override {
		if (_battleground->_isInFight && _battleground->_monsterNum == kTyphoon) {
			_typhoon->handleClick(_typhoon, name);
			return;
		}

		if (_battleground->_isInFight && _battleground->_monsterNum == kIllusion) {
			_illusion->handleClick(name);
			return;
		}
	}

	void handleEvent(int eventId) override {
		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
		Persistent *persistent = g_vm->getPersistent();

		_typhoon->handleEvent(eventId);
		_cyclops->handleEvent(eventId);
		_illusion->handleEvent(eventId);

		switch (eventId) {
		case 524:
			g_vm->getHeroBelt()->setBranchOfLifeFrame(0);
			break;
		case 526:
			g_vm->getHeroBelt()->setThunderboltFrame(kLightning3);
			break;

		case 15351:
			room->playAnimWithMusic(kZeusLight, "G0260MA0", kZeusLightZ,
						PlayAnimParams::keepLastFrame().partial(0, 4),
						15379); // 15379(anim), 15381(-1), 15359(sound)
			break;
		case 15352:
			room->playVideo("V7190BA0", 0, 15386, Common::Point(0, 216));
			break;
		case 15353:
			room->playAnim(kZeusLight, kZeusLightZ,
				       PlayAnimParams::disappear().partial(4, -1),
				       15358);
			break;
		case 15355:
			room->playSpeech(TranscribedSound::make("V7100WC0",
							  "I'm giving you these thunderbolts to "
							  "use against Hades' monsters."),
					 15364);
			g_vm->getHeroBelt()->setThunderboltFrame(kLightning2);
			g_vm->addTimer(526, 5000);
			break;
		case 15356:
			room->playVideo("V7180BB0", 0, 15361, Common::Point(0, 216));
			break;
		case 15357:
			room->playSpeech(g_vm->getRnd().getRandomBit()
					 ? TranscribedSound::make("V7150WC0", "Get back in there. Here is another branch")
					 : TranscribedSound::make("V7150WB0", "Here's another branch. Keep going"),
					 15353);
			break;
		case 15358:
			switch (_battleground->_monsterNum) {
			case kCyclops:
				room->playVideo("V7180BB0", 0, 15389, Common::Point(0, 216));
				break;
			case kTyphoon:
				room->playVideo("V7210BB0", 0, 15387, Common::Point(0, 216));
				break;
			case kIllusion:
				room->playVideo("V7220BR0", 0, 15382, Common::Point(0, 216));
				break;
			}
			break;
		case 15361:
			g_vm->addTimer(15391, 100);
			break;
		case 15364:
			room->playSpeech(TranscribedSound::make(
					     "V7100WD0",
					     "Ah, and this branch of life will let "
					     "you to remain in the underworld until "
					     "all of its leaves have fallen"),
				15365);
			_battleground->_leavesRemaining = 9;
			g_vm->getHeroBelt()->setBranchOfLifeFrame(1);
			g_vm->addTimer(524, 5000);
			break;
		case 15365:
			room->playSpeech(TranscribedSound::make(
						 "V7100WE0",
						 "Use your thunderbolts and your hero powers "
						 "to battle the monsters of the underworld"), 15366);
			_countOfIntroLightning = 0;
			introLightning();
			break;
		case 15366:
			room->playSpeech(TranscribedSound::make(
						 "V7100WF0",
						 "Move your mouse to aim and click to fire your thunderbolts. "
						 "And don't forget: you can now use your hero powers"),
					 15367);
			break;
		case 15367:
			room->playSpeech(TranscribedSound::make(
						 "V7100WH0",
						 "And remember to keep an eye on your branch. "
						 "When the last leaf drops, you'll be "
						 "banished from the underworld"),
					 15368);
			break;
		case 15368:
			room->playSpeech(TranscribedSound::make(
						 "V7100WI0",
						 "This is the ultimate test but I know you can do it"),
					 15369);
			break;
		case 15369:
			room->playAnim(kZeusLight, kZeusLightZ,
				       PlayAnimParams::disappear().partial(4, -1),
				       15356);
			break;
		case 15370:
			if (++_countOfIntroLightning < 4)
				introLightning();
			break;
		case 15374:
			room->playAnimWithMusic(kZeusLight, "G0260MA0", kZeusLightZ,
						PlayAnimParams::keepLastFrame().partial(0, 4),
						15375);
			break;
		case 15375:
			room->playSpeech(revitalisedSound(), 15376);
			replenishPowers();
			break;
		case 15376:
			room->playAnim(kZeusLight, kZeusLightZ,
				       PlayAnimParams::disappear().partial(4, -1),
				       15377);
			break;
		case 15377:
			room->playVideo("V7210BB0", 0, 15387, Common::Point(0, 216));
			break;
		case 15378:
			handleEvent(15390);
			break;
		case 15379:
			room->playSpeech(revitalisedSound(), 15380);
			replenishPowers();
			break;
		case 15380:
			room->playAnim(kZeusLight, kZeusLightZ,
				       PlayAnimParams::disappear().partial(4, -1),
				       15381);
			break;
		case 15381:
			room->playVideo("V7220BR0", 0, 15388, Common::Point(0, 216));
			break;
		case 15382:
			g_vm->addTimer(15392, 100);
			break;
		case 15383:
			if (persistent->_quest == kRescuePhilQuest)
				g_vm->moveToRoom(kHadesThroneRoom);
			else {
				_battleground->_level++;
				_cyclops->enterCyclops(_battleground->_level);
			}
			break;
		case 15386:
			// unclear
			room->playSpeech(
				persistent->_gender == kMale
				? TranscribedSound::make(
					"V7190WB0",
					"One more word out of your goat-brain "
					"and I'm gonna have your face for lambchops, alright? "
					"This kid's gonna have to make it on his own, ok?")
				: TranscribedSound::make(
					"V7190WC0",
					"One more word out of your goat-brain "
					"and I'm gonna have your face for lambchops, ok? "
					"This kid's gonna have to make it on her own."),
				15374);
			break;
		case 15387:
			room->playSpeech(
				persistent->_gender == kMale
				? TranscribedSound::make(
					"V7210WB0",
					"Oh, you want to be a hero? "
					"Well you're gonna die a hero's death. "
					"Typhoon's gonna chew you up in little "
					"pieces and spit you out like a meatgrinder, kid")
				: TranscribedSound::make(
					"V7210WC0",
					"Oh, you want to be a heroine? "
					"Well you're gonna die a gruesome death. "
					"Typhoon's gonna chew you up in little "
					"pieces and spit you out like a meatgrinder, little princess."),
				15378);
			break;
		case 15388:
			room->playSpeech(TranscribedSound::make(
						 "V7220WB1",
						 "You dare to think you can outwit me? "
						 "You, my little friend, will be ripped to shreads and slowly digested for eternity "
						 "inside a belly of a thousand hideous creatures. You will die a thousand agonizing "
						 "deaths as I now bring down upon you all the forces of Hades."),
				15382);
			break;
		case 15389:
			// unclear
			room->playSpeech(TranscribedSound::make(
						 "V7180WB0",
						 "Hey, there. Hi, there. Hoi, there. "
						 "And welcome to my world. "
						 "You know what they say: \"My world - my rules\". "
						 "So here is the rule number one: No trespassing. "
						 "My bouncer will show you the way out. Have a nice day"),
					 15361);
			break;
		case 15390:
			_typhoon->enterTyphoon(1);
			break;
		case 15391:
			_cyclops->enterCyclops(1);
			break;
		case 15392:
			_illusion->enterIllusion(1);
			break;
		case 15465:
			_playingShootingSound = false;
			break;
		case kHitReceived:
			_battleground->_leavesRemaining--;
			if (_battleground->_leavesRemaining >= 0)
				g_vm->getHeroBelt()->setBranchOfLifeFrame(10 - _battleground->_leavesRemaining);
			if (_battleground->_leavesRemaining <= 0) {
				_battleground->stopFight();
				room->disableMouse();
				room->playAnimWithMusic(kZeusLight, "G0260MA0", kZeusLightZ,
							PlayAnimParams::keepLastFrame().partial(0, 4),
							15357);
			}
			break;
		}
	}

	void prepareRoom() override {
		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
		g_vm->getHeroBelt()->setColour(HeroBelt::kCold);
		room->loadHotZones("Monster.HOT", false);
		room->addStaticLayer("v7010pa0", kBackgroundZ, Common::Point(-10, -10)); // background
		// event 15362+15363

		room->disableMouse();
		_battleground->_monsterNum = kCyclops;
		room->playAnimWithMusic(kZeusLight, "G0260MA0", kZeusLightZ,
					PlayAnimParams::keepLastFrame().partial(0, 4),
					15355);
	}

	void frameCallback() override {
		_battleground->tick();
		_illusion->tick();
	}

	void handleAbsoluteClick(Common::Point p) override {
		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
		if (!_battleground->_isInFight)
			return;
		_battleground->handleAbsoluteClick(p);

		HeroPower hp = g_vm->getHeroBelt()->getSelectedStrength();
		bool isStrong = hp == kPowerStrength;

		if (p.x < kLightningCutoff) {
			room->playAnim(isStrong ? "v7130ba2" : "v7130ba0", 300, PlayAnimParams::disappear(), EventHandlerWrapper(), p);
		} else {
			room->playAnim(isStrong ? "v7130ba3" : "v7130ba1", 300, PlayAnimParams::disappear(),
				       EventHandlerWrapper(), p - Common::Point(kLightningCutoff, 0));
		}

		if (!_playingShootingSound) {
			switch (hp) {
			case kPowerStealth:
				room->playSFX("v7130ea0");
				break;
			case kPowerStrength:
				room->playSFX("v7130eb0");
				break;
			case kPowerWisdom:
				room->playSFX("v7130ec0");
				break;
			case kPowerNone:
				room->playSFX("v7130ee0");
				break;
			}
			_playingShootingSound = true;
			g_vm->addTimer(15465, g_vm->getRnd().getRandomNumberRng(300, 600));
		}

		switch (_battleground->_monsterNum) {
		case kCyclops:
			_cyclops->handleClick(p);
			break;
		case kTyphoon:
			break;
		case kIllusion:
			_illusion->handleAbsoluteClick(p);
			break;
		}
	}

private:
	void replenishPowers() {
		g_vm->getHeroBelt()->setThunderboltFrame(kLightning2);
		g_vm->addTimer(526, 5000);
		_battleground->_leavesRemaining = 9;
		g_vm->getHeroBelt()->setBranchOfLifeFrame(1);
		g_vm->addTimer(524, 5000);
	}

	void introLightning() {
		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
		Common::Point target = Common::Point(
			g_vm->getRnd().getRandomNumberRng(150, 450),
			g_vm->getRnd().getRandomNumberRng(50, 350));
		if (target.x < kLightningCutoff) {
			room->playAnim("v7130ba0", 300, PlayAnimParams::disappear(), 15370, target);
		} else {
			room->playAnim("v7130ba1", 300, PlayAnimParams::disappear(), 15370,
				       target - Common::Point(kLightningCutoff, 0));
		}
		room->playSFX("v7130eb0");
	}

	bool _playingShootingSound;
	int _countOfIntroLightning;
	Common::SharedPtr<Battleground> _battleground;
	Common::SharedPtr<Typhoon> _typhoon;
	Common::SharedPtr<Cyclops> _cyclops;
	Common::SharedPtr<Illusion> _illusion;
};

Common::SharedPtr<Hadesch::Handler> makeMonsterHandler() {
	return Common::SharedPtr<Hadesch::Handler>(new MonsterHandler());
}

}
