#include "Textbox.h"
#include "olcUTIL_Geometry2D.h"
#include "util.h"

Textbox::Textbox(){};

void Textbox::Initialize(std::string text,vf2d pos,std::string headerText,Renderable*boxImg,vf2d maxSize,Audio*dialogSound,std::vector<Memory>resourceCost,float letterDisplayDelay)
{
	if(GetCurrentString()!=text){ //Make sure this is actually a new textbox
		SetDefaults();
		this->text=text;
		this->headerText=headerText;
		this->maxSize=maxSize;
		this->resourceCost=resourceCost;
		this->letterDisplayDelay=letterDisplayDelay;
		this->boxImg=boxImg;
		if(this->dialogSound!=nullptr){
			this->dialogSound->Stop(soundHandle);
			this->dialogSound=nullptr;
		}
		if(dialogSound!=nullptr){
			this->dialogSound=dialogSound;
			soundHandle=this->dialogSound->PlayCentered(1,audioVolume,true);
		}
		visible=true;
	}
}

void Textbox::SetDefaults(){
	lastLetterTime=0;
	textboxMarker=-1;
	lastWordMarker=-1;
	lastWord="";
	lastHeaderWordMarker=-1;
	lastHeaderWord="";
	displayText="";
	displayHeaderText="";
	text="";
	headerText="";
	audioVolume=0;
	continueWordTimer=0;
	bPressed=false;
}

void Textbox::Update(PixelGameEngine*pge){
	if(!visible){
		if(dialogSound!=nullptr){
			audioVolume=std::max(0.f,audioVolume-pge->GetElapsedTime()*2);
			dialogSound->SetVolume(soundHandle,audioVolume);
		}
		return;
	}
	lastLetterTime-=pge->GetElapsedTime();
	continueWordTimer+=pge->GetElapsedTime();
	if(lastLetterTime<=0){
		if(textboxMarker<int(text.length()-1)){
			std::string tempText=displayText;
			tempText+=text[textboxMarker+1];

			auto WrapText=[&](std::string&tempText,std::string&text,std::string&displayText,int&lastWordMarker,std::string&lastWord){
				vf2d maxSize=this->maxSize;
				if(boxImg!=nullptr){
					maxSize-={26,0};
				}
				if(pge->GetTextSizeProp(tempText).x>=maxSize.x){
					displayText=displayText.substr(0,lastWordMarker);
					displayText+='\n';
					displayText+=lastWord;
				}
				if(text[textboxMarker+1]==' '||text[textboxMarker+1]=='\n'){
					lastWord="";
					lastWordMarker=textboxMarker+2;
				} else {
					lastWord+=text[textboxMarker+1];
				}
				displayText+=text[textboxMarker+1];
			};

			WrapText(tempText,text,displayText,lastWordMarker,lastWord);

			if(textboxMarker<int(headerText.length()-1)){
				std::string tempHeaderText=displayHeaderText;
				tempHeaderText+=headerText[textboxMarker+1];
				WrapText(tempHeaderText,headerText,displayHeaderText,lastHeaderWordMarker,lastHeaderWord);
			}
			textboxMarker++;
			if(dialogSound!=nullptr){
				audioVolume=std::min(1.f,audioVolume+0.01f*2);
				dialogSound->SetVolume(soundHandle,audioVolume);
				audioFadeOutDelay=2;
			}
		}else{
			if(dialogSound!=nullptr){
				audioFadeOutDelay=std::max(0.f,audioFadeOutDelay-0.01f);
				if(audioFadeOutDelay<=0){
					audioVolume=std::max(0.f,audioVolume-0.01f*2);
					dialogSound->SetVolume(soundHandle,audioVolume);
				}
			}
		}
		maxSize.y=std::max(maxSize.y,float(pge->GetTextSizeProp(displayHeaderText).y+pge->GetTextSizeProp(displayText).y));
		lastLetterTime=letterDisplayDelay;
	}
	if(textboxMarker>=int(text.length()-1)){
		bPressed=pge->GetMouse(0).bPressed||pge->GetMouse(1).bPressed;
	}
}


void Textbox::Draw(PixelGameEngine*pge,Resources&resources,std::vector<std::unique_ptr<Renderable>>&IMAGES,int totalUsedMemory,int memoryLimit){
	if(visible){
		geom2d::rect<float>boundingRect={pos-vf2d{3,3},maxSize+vf2d{6,6}};
		if(resourceCost.size()>0){
			boundingRect.size.x+=36;
			boundingRect.size.y=std::max(36.f,boundingRect.size.y);
		}
		if(boxImg!=nullptr){
			boundingRect.size.x+=26;
		}
		if(boundingRect.bottom().start.y>=pge->ScreenHeight()){
			boundingRect.pos-={0,boundingRect.bottom().start.y-pge->ScreenHeight()};
		}
		if(boundingRect.right().start.x>=pge->ScreenWidth()){
			boundingRect.pos-={boundingRect.right().start.x-pge->ScreenWidth(),0};
		}
		if(boundingRect.top().start.y<0){
			boundingRect.pos+={0,-boundingRect.top().start.y};
		}
		if(boundingRect.left().start.x<0){
			boundingRect.pos+={-boundingRect.left().start.x,0};
		}
		geom2d::rect<float>textboxRect=boundingRect;
		if(boxImg!=nullptr){
			textboxRect.pos.x+=26;
			textboxRect.size.x-=50;
		}
		pge->FillRectDecal(boundingRect.pos,maxSize+vf2d{6,6},backCol);
		pge->DrawRectDecal(boundingRect.pos+vf2d{1,1},maxSize+vf2d{4,4},WHITE);
		if(boxImg!=nullptr){
			pge->DrawDecal(boundingRect.pos+vf2d{3,3},IMAGES[MATRIX]->Decal(),{0.375,0.375},DARK_GREY);
			pge->DrawDecal(boundingRect.pos+vf2d{3,3},boxImg->Decal());
			pge->DrawRectDecal(boundingRect.pos+vf2d{3,3},{24,24},YELLOW);
		}
		pge->DrawShadowStringPropDecal(textboxRect.pos+vf2d{3,3},displayHeaderText,{245, 218, 66});
		pge->DrawShadowStringPropDecal(textboxRect.pos+vf2d{3.f,float(3+pge->GetTextSizeProp(displayHeaderText).y)},displayText,{220,220,220});
		if(textboxMarker==int(text.length()-1)&&boxImg!=nullptr){
			std::string continueText="Click to Continue";
			pge->DrawShadowStringPropDecal(textboxRect.pos+textboxRect.size-vf2d(pge->GetTextSizeProp(continueText))*vf2d{0.6,1}-vf2d{5,-9},continueText,{255,255,255,uint8_t(abs(sin(2*continueWordTimer))*255)},{0,0,0,uint8_t(abs(sin(2*continueWordTimer))*255)},{0.6,1});
		}
		if(resourceCost.size()>0){
			geom2d::rect<float>resourceBoxRect={textboxRect.pos+vf2d{6+maxSize.x,0},{36,42}};
			pge->FillRectDecal(resourceBoxRect.pos,resourceBoxRect.size,backCol);
			pge->DrawRectDecal(resourceBoxRect.pos+vf2d{1,1},resourceBoxRect.size-vf2d{2,2},WHITE);
			vf2d contentPos=resourceBoxRect.pos+vf2d{3,3};

			Pixel drawcol=GREY,shadowCol={66, 164, 245};

			auto DrawResourceAmount=[&](int index,int cost,int resourceAmt){
				drawcol=resourceAmt>=cost?GREY:RED;
				shadowCol=drawcol==GREY?VERY_DARK_BLUE:VERY_DARK_RED;
				vf2d textScale = {0.4,0.4};
				std::string displayString = std::to_string(resourceAmt)+(resourceAmt<10?" ":"")+"/";
				if(resourceAmt<cost){
					pge->FillRectDecal(contentPos+vf2d{0,float(index*6)},vf2d{resourceBoxRect.size.x-6,6},{160,0,0,192});
				}
				pge->DrawShadowStringDecal(contentPos+vf2d{12.f,float(index*6)+1},displayString,drawcol,shadowCol,textScale,0.6);
				pge->DrawShadowStringDecal(contentPos+vf2d{12.f+pge->GetTextSize(displayString).x*textScale.x+2,float(index*6)+1},std::to_string(cost),drawcol,shadowCol,{0.4,0.4},0.6);
			};

			int index=0;
			int totalCost=0;
			if(util::GetHealthCost(resourceCost)!=-1){
				DrawResourceAmount(index,util::GetHealthCost(resourceCost),resources.health);
				pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE]->Decal(),{0.5,0.5},CONSTANT::HEALTH_COLOR);
				totalCost+=util::GetHealthCost(resourceCost);
				index++;
			}
			if(util::GetAtkSpdCost(resourceCost)!=-1){
				DrawResourceAmount(index,util::GetAtkSpdCost(resourceCost),resources.atkSpd);
				pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE]->Decal(),{0.5,0.5},CONSTANT::ATKSPD_COLOR);
				totalCost+=util::GetAtkSpdCost(resourceCost);
				index++;
			}
			if(util::GetMoveSpdCost(resourceCost)!=-1){
				DrawResourceAmount(index,util::GetMoveSpdCost(resourceCost),resources.moveSpd);
				pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE]->Decal(),{0.5,0.5},CONSTANT::MOVESPD_COLOR);
				totalCost+=util::GetMoveSpdCost(resourceCost);
				index++;
			}
			if(util::GetRangeCost(resourceCost)!=-1){
				DrawResourceAmount(index,util::GetRangeCost(resourceCost),resources.range);
				pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE]->Decal(),{0.5,0.5},CONSTANT::RANGE_COLOR);
				totalCost+=util::GetRangeCost(resourceCost);
				index++;
			}
			if(util::GetProcedureCost(resourceCost)!=-1){
				DrawResourceAmount(index,util::GetProcedureCost(resourceCost),resources.procedure);
				pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE]->Decal(),{0.5,0.5},CONSTANT::PROCEDURE_COLOR);
				totalCost+=util::GetProcedureCost(resourceCost);
				index++;
			}
			std::string text="Size: "+std::to_string(totalCost)+" bytes";
			vi2d size=pge->GetTextSizeProp(text);
			drawcol=WHITE;
			if(totalCost+totalUsedMemory>memoryLimit){
				pge->FillRectDecal(contentPos+vf2d{-1,float(index*6)},vf2d{resourceBoxRect.size.x-4,7},{160,0,0,192});
				drawcol=RED;
			}
			pge->DrawShadowStringPropDecal(contentPos+vf2d{0,index*6.f+1},text,drawcol,BLACK,{30/float(size.x),0.5},0.6);
			index++;
		}
	}
}

void Textbox::UpdatePosition(vf2d newPos){
	pos=newPos;
}

std::string&Textbox::GetCurrentString(){
	return text;
}

void Textbox::SetVisible(bool visible){
	this->visible=visible;
	if(!visible){
		SetDefaults();
	}
}

void Textbox::UpdateAndDraw(vf2d pos,PixelGameEngine*pge,Resources&resources,std::vector<std::unique_ptr<Renderable>>&IMAGES,int totalUsedMemory,int memoryLimit){
	UpdatePosition(pos);
	Update(pge);
	Draw(pge,resources,IMAGES,totalUsedMemory,memoryLimit);
}

vf2d Textbox::GetSize(){
	return maxSize;
}

void Textbox::SetBackgroundColor(Pixel col){
	backCol=col;
}

bool Textbox::IsVisible(){
	return visible;
}