#include "Scenario.h"
#include "TileManager.h"


Scenario::Scenario(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
:units(units),IMAGES(IMAGES),SOUNDS(SOUNDS),objective(objective),game(game),flags(flags){}
Scenario::~Scenario(){};
void Scenario::_Start(){
	state=0;
	camera=utils::Camera2D{game.GetPGE()->GetScreenSize(),game.GetWorldOffset()};
	camera.SetLazyFollowRate(2);
	camera.SetMode(utils::Camera2D::Mode::LazyFollow);
	targetPos={96,96};
	box.SetVisible(false);
	initialWaitTime=3;
	camera.SetTarget(targetPos);
	missionCompletedTimer=0;
	transitionToNextLevel=false;
	Start();
}
void Scenario::Start(){};
void Scenario::_Update(){
	initialWaitTime=std::max(0.f,initialWaitTime-game.GetPGE()->GetElapsedTime());
	missionFinishWaitTime=std::max(0.f,missionFinishWaitTime-game.GetPGE()->GetElapsedTime());
	smallTimePass=std::min(1.f,smallTimePass+game.GetPGE()->GetElapsedTime());
	if(flags.playerInControl){
		smallTimePass=0;
	}
	if(missionCompleted){
		missionCompletedTimer+=game.GetPGE()->GetElapsedTime();
	} else {
		missionCompleted=MissionCompleted();
	}
	if(initialWaitTime==0){
		Update();
	}
};
bool Scenario::MissionCompleted(){return false;}
void Scenario::Update(){};
void Scenario::Draw(){
	if(objective.length()>0){
		game.GetPGE()->DrawShadowStringDecal({4,24},"Objective:");
		game.GetPGE()->DrawShadowStringDecal({6,36},objective);
		game.GetPGE()->DrawShadowStringDecal({4,24},missionCompleted?"Objective Complete!":"Objective:",missionCompleted?GREEN:WHITE);
		vf2d textSize=game.GetPGE()->GetTextSize(objective);
		game.GetPGE()->DrawShadowStringDecal({6,36},objective,missionCompleted?GREEN:WHITE);
		if(missionCompleted&&missionFinishWaitTime==0){
			game.GetPGE()->FillRectDecal(vf2d{6,36}+vf2d{0,textSize.y/2-1},{textSize.x,3});
			std::string continueText="< Press [Spacebar] to continue >";
			vf2d textScale={2,3};
			vf2d textSize=game.GetPGE()->GetTextSizeProp(continueText)*textScale;
			game.GetPGE()->DrawShadowStringPropDecal(game.GetPGE()->GetScreenSize()/2-textSize/2+vf2d{0,72},continueText,{255,255,255,uint8_t(abs(sin(2*missionCompletedTimer))*255)},{0,0,0,uint8_t(abs(sin(2*missionCompletedTimer))*255)},textScale);
			if(game.GetPGE()->GetKey(SPACE).bPressed){
				transitionToNextLevel=true;
			}
		}
	}
	Resources temp={0,0,0,0,0};
	box.UpdateAndDraw({24,64},game.GetPGE(),temp,IMAGES,0,0);
}
void Scenario::SetCameraTarget(vf2d pos,bool instant){
	if(instant){camera.SetMode(utils::Camera2D::Mode::Simple);} else {camera.SetMode(utils::Camera2D::Mode::LazyFollow);}
	targetPos=pos;
	camera.SetTarget(targetPos);
	camera.Update(game.GetPGE()->GetElapsedTime());
	game.SetWorldOffset(camera.GetViewPosition());
}
void Scenario::SetObjective(std::string objective){
	this->objective=objective;
}
void Scenario::RevealTiles(vf2d pos){
	for(int y=-1;y<=1;y++){
		for(int x=-1;x<=1;x++){
			vi2d basePos={int(pos.x+x*96),int(pos.y+y*96)};
			TileManager::visibleTiles[{basePos.x/96,basePos.y/96}]=30;
		}
	}
}
Stage1::Stage1(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage1::Start(){
	flags.unitMetersGreyedOut=true;
	flags.playerInControl=false;
	nextLevel=LevelName::STAGE2;
};
void Scenario::DisplayBox(std::string text,bool scaryHoodedFigure){
	if(smallTimePass==1){
		box.Initialize(text,{24,64},"",scaryHoodedFigure?IMAGES[SPOOK_HOODED_FIGURE].get():IMAGES[HOODED_FIGURE].get(),{378,28},SOUNDS[Sound::VOICEOVER].get());
	}
}
void Stage1::Update(){
	switch(state){
	case 0:{
		DisplayBox("Hello Hacker, thank you for taking on this request for me.");
		if(box.bPressed){
			state=1;
		}
	}break;
	case 1:{
		DisplayBox("It appears we have no time to waste, many sectors are already infected and the virus spread will just keep getting worse.");
		if(box.bPressed){
			state=2;
			SOUNDS[Sound::PING]->PlayCentered();
			RevealTiles({320,320});
		}
	}break;
	case 2:{
		SetCameraTarget({320,320});
		if(camera.ReachedTarget()){
			state=3;
		}
	}break;
	case 3:{
		DisplayBox("Your mission is to take out all the RAM banks from the system, this will stop any further creation and spread of viruses.");
		if(box.bPressed){
			state=4;
		}
	}break;
	case 4:{
		SetCameraTarget({128,128});
		if(camera.ReachedTarget()){
			state=5;
		}
	}break;
	case 5:{
		DisplayBox("The yellow bars represent units' allocated Health memory. Take out the enemies' and make sure you always have at least 1 bit of it.");
		if(box.bPressed){
			state=6;
		}
	}break;
	case 6:{
		DisplayBox("Drag over your target unit and then select a target location via right-click.");
		if(box.bPressed){
			state=7;
		}
	}break;
	case 7:{
		SetObjective("Defeat the RAM bank");
		DisplayBox("That should be all you need for now. I'll be back after my coffee break.");
		if(box.bPressed){
			state=8;
			box.SetVisible(false);
			flags.playerInControl=true;
		}
	}break;
	case 8:{
	}break;
	}
};
bool Stage1::MissionCompleted(){
	for(auto&u:units){
		if(!u->IsFriendly()&&u->IsRAMBank()){
			return false;
		}
	}
	return true;
}
Stage2::Stage2(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
	:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage2::Start(){
	flags.playerInControl=false;
	flags.limitedBuildOptions=true;
	nextLevel=LevelName::STAGE3;
};
void Stage2::Update(){
	switch(state){
		case 0:{
			SetCameraTarget({7*24,10*24},true);
			DisplayBox("You took care of that sector flawlessly Hacker, this next one needs a bit more hand-holding.");
			if(box.bPressed){
				state=1;
			}
		}break;
		case 1:{
			DisplayBox("We have analyzed the data from the RAM bank and can now create one. Go ahead and select the Platform here and construct one.");
			if(box.bPressed){
				state=2;
				box.SetVisible(false);
				flags.playerInControl=true;
			}
		}break;
		case 2:{
			for(auto&u:units){
				if(u->IsRAMBank()&&u->IsFriendly()){
					state=3;
					flags.playerInControl=false;
					break;
				}
			}
		}break;
		case 3:{
			DisplayBox("Excellent, each RAM bank has the capability to allocate memory into the system. See that indicator down below?");
			flags.flashMemoryBar=true;
			if(box.bPressed){
				state=4;
			}
		}break;
		case 4:{
			DisplayBox("This sector lets us allocate 30 bytes of RAM. That's 240 bits for the savvy folks out there.");
			if(box.bPressed){
				state=5;
				flags.flashMemoryBar=false;
			}
		}break;
		case 5:{
			DisplayBox("Some of it has already been used up by our RAM bank and other system resources... ");
			if(box.bPressed){
				state=6;
			}
		}break;
		case 6:{
			DisplayBox("To allocate 5 bits, select the RAM bank and click the Memory Allocator button.\n\nGive it a try now.");
			if(box.bPressed){
				state=7;
				box.SetVisible(false);
				flags.playerInControl=true;
			}
		}break;
		case 7:{
			for(auto&u:units){
				if(u->IsAllocator()&&u->IsFriendly()){
					state=8;
					flags.playerInControl=false;
					break;
				}
			}
		}break;
		case 8:{
			DisplayBox("Now select the memory allocator and let's make a Shifter unit.");
			if(box.bPressed){
				state=9;
				box.SetVisible(false);
				flags.playerInControl=true;
			}
		}break;
		case 9:{
			for(auto&u:units){
				if(!u->IsAllocator()&&!u->IsRAMBank()&&u->IsFriendly()){
					state=10;
					flags.playerInControl=false;
					break;
				}
			}
		}break;
		case 10:{
			DisplayBox("The memory shifters will be your primary way to delete memory from units.");
			if(box.bPressed){
				state=11;
				SOUNDS[Sound::ALARM]->PlayCentered();
			}
		}break;
		case 11:{
			SetCameraTarget({22*24,23*24});
			RevealTiles({22*24,23*24});
			if(camera.ReachedTarget()){
				state=12;
			}
		}break;
		case 12:{
			SetObjective("Defeat all enemy units.");
			DisplayBox("I have detected viruses in the system again. Please eradicate them and free system resources.");
			if(box.bPressed){
				state=13;
				flags.playerInControl=true;
				box.SetVisible(false);
			}
		}break;
	}
};
bool Stage2::MissionCompleted(){
	for(auto&u:units){
		if(!u->IsFriendly()){
			return false;
		}
	}
	return true;
}
Stage3::Stage3(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
	:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage3::Start(){
	nextLevel=LevelName::STAGE4;
};
void Stage3::Update(){
	switch(state){
	case 0:{

	}break;
	}
};
bool Stage3::MissionCompleted(){
	return false;
}
Stage4::Stage4(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
	:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage4::Start(){
	nextLevel=LevelName::STAGE5;
};
void Stage4::Update(){
	switch(state){
	case 0:{

	}break;
	}
};
bool Stage4::MissionCompleted(){
	return false;
}
Stage5::Stage5(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
	:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage5::Start(){
	nextLevel=LevelName::STAGE6;
};
void Stage5::Update(){
	switch(state){
	case 0:{

	}break;
	}
};
bool Stage5::MissionCompleted(){
	return false;
}
Stage6::Stage6(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
	:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage6::Start(){
	nextLevel=LevelName::STAGE7;
};
void Stage6::Update(){
	switch(state){
	case 0:{

	}break;
	}
};
bool Stage6::MissionCompleted(){
	return false;
}
Stage7::Stage7(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
	:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage7::Start(){
	nextLevel=LevelName::STAGE8;
};
void Stage7::Update(){
	switch(state){
	case 0:{

	}break;
	}
};
bool Stage7::MissionCompleted(){
	return false;
}
Stage8::Stage8(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage8::Start(){
	nextLevel=LevelName::FINISH;
};
void Stage8::Update(){
	switch(state){
	case 0:{

	}break;
	}
};
bool Stage8::MissionCompleted(){
	return false;
}