#include "Help.as";

#define CLIENT_ONLY

// globals - we can because this is only run by one (my) player
ConfigFile done;
bool loaded = false;		
const f32 HELP_DISTANCE = 2.0f;
HelpText[] renderHelps;
u32 lastSaveTime = 0;

void onInit( CSprite@ this )
{
	this.getCurrentScript().runFlags |= Script::tick_myplayer;
	this.getCurrentScript().removeIfTag = "dead";
	//this.getCurrentScript().tickFrequency = 30;
}

void Done( const string &in name, const string &in prefix )
{
	const string name2 = prefix + " " + name;
	if (done.exists(name2)) 
	{
		int amount = 1 + done.read_u32( name2 );
		done.add_u32( name2, amount );
	}
	else
		done.add_u32( name2, 1 );
}

void onTick( CSprite@ this )
{
	if (g_videorecording)
		return;
	CBlob@ blob = this.getBlob();
	const u32 gametime = getGameTime();

	CBlob@[] blobsInRadius;
	CMap@ map = blob.getMap();
	CInventory@ inv = blob.getInventory();
	CBlob@ carried = blob.getCarriedBlob();
		
	if (!sv_test && !loaded)
	{
		if (!done.loadFile("../Cache/HelpDone.cfg"))
			done.saveFile("../Cache/HelpDone.cfg");		
		else
			loaded = true;
	}

	// seated

	if (blob.isAttached())
	{	
		if (blob.isKeyJustReleased( key_action1 ))
		{	
			AttachmentPoint@ ap = blob.getAttachments().getAttachmentPointByName("GUNNER");
			if (ap !is null && ap.getOccupied() !is null && isRecipientOfHelp( blob, ap.getOccupied(), "help GUNNER action" ))
			{
				Done( "done help GUNNER action", blob.getName() );
			}
		}

		if (blob.isKeyJustReleased( key_down ) || blob.isKeyJustReleased( key_left ) || blob.isKeyJustReleased( key_right ))
		{	
			AttachmentPoint@ ap = blob.getAttachments().getAttachmentPointByName("DRIVER");
			if (ap !is null && ap.getOccupied() !is null && isRecipientOfHelp( blob, ap.getOccupied(), "help DRIVER movement" ))
			{
				Done( "done help DRIVER movement", blob.getName() );
			}
		}
	}
	else
	{
		// near 

		if (map !is null && map.getBlobsInRadius( blob.getPosition(), blob.getRadius() + HELP_DISTANCE, @blobsInRadius )) 
		{
			for (uint i = 0; i < blobsInRadius.length; i++)
			{
				CBlob @b = blobsInRadius[i]; 
				if (b !is blob) 
				{	 
					if (blob.isKeyJustReleased( key_use ) && isRecipientOfHelp( blob, b, "help use" )) {
						Done( "done help use", b.getName() );
					}

					if (blob.isKeyJustReleased( key_action1 ) && isRecipientOfHelp( blob, b, "help action" )) {
						Done( "done help action", b.getName() );
					}

					if (blob.isKeyJustReleased( key_action2 )) {
						if (isRecipientOfHelp( blob, b, "help action2" ))
						Done( "done help action2", b.getName() );
					}

					if (blob.isKeyJustReleased( key_up ) && isRecipientOfHelp( blob, b, "help jump" )) {
						Done( "done help jump", b.getName() );
					}

					if (blob.isKeyJustReleased( key_down ) && isRecipientOfHelp( blob, b, "help hop" )) {
						Done( "done help hop", b.getName() );
					}

					if (gametime % 30 == 0 && isRecipientOfHelp( blob, b, "help show" )) {
						Done( "done help show", b.getName() );
					}
				}
			}
		}

		// carried

		if (carried !is null)
		{	 
			if (isRecipientOfHelp( blob, carried, "help pickup" )) {
				Done( "done help pickup", carried.getName() );
			}

			if (blob.isKeyJustReleased( key_action3 ) && isRecipientOfHelp( blob, carried, "help activate" )) {
					Done( "done help activate", carried.getName() );
			}

			if (blob.isKeyJustReleased( key_action3 ) && isRecipientOfHelp( blob, carried, "help rotate" )) {
				Done( "done help rotate", carried.getName() );
			}

			if (blob.isKeyJustReleased( key_action3 ) && isRecipientOfHelp( blob, carried, "help throw" ) && carried.hasTag("activated")) 
			{
				Done( "done help throw", carried.getName() );

				// hack:
				if (carried.getName() == "bomb") {
					Done( "done help activate", "mat_bombs" );
				}			
			}

			if (blob.isKeyJustReleased( key_use ) && isRecipientOfHelp( blob, carried, "help use carried" )) {
				Done( "done help use carried", carried.getName() );
			}

		}

		// inventory

		for (int i = 0; i < inv.getItemsCount(); i++)
		{
			CBlob @b = inv.getItem(i);	
			
			if (blob.isKeyJustReleased( key_inventory ) && isRecipientOfHelp( blob, b, "help switch" )) {
				Done( "done help switch", b.getName() );
			}
		}

		// general - self

		if (blob.isKeyJustReleased( key_action2 ) && isRecipientOfHelp( blob, blob, "help self action2" )) {
			Done( "done help self action2", blob.getName() );
		}

		if (blob.isKeyJustReleased( key_action1 ) && isRecipientOfHelp( blob, blob, "help self action" )) {
			Done( "done help self action", blob.getName() );
		}

		if (carried !is null && blob.isKeyJustReleased( key_pickup ) && isRecipientOfHelp( blob, blob, "help throw" )) {
			Done( "done help throw", blob.getName() ); 
		}

		if (carried !is null && blob.isKeyJustReleased( key_inventory ) && isRecipientOfHelp( blob, blob, "help putback" )) {
			Done( "done help putback", blob.getName() ); 
		}

		if (blob.isKeyJustReleased( key_inventory ) && isRecipientOfHelp( blob, blob, "help inventory" )) {
			Done( "done help inventory", blob.getName() ); 
		}

		if ((blob.isKeyJustReleased( key_up ) || blob.isKeyJustReleased( key_left ) || blob.isKeyJustReleased( key_right )) && isRecipientOfHelp( blob, blob, "help movement" )) {
			Done( "done help movement", blob.getName() ); 
		}

		if (blob.isKeyJustReleased( key_down ) && isRecipientOfHelp( blob, blob, "help self hide" )) {
			Done( "done help self hide", blob.getName() );
		}													  

		if (gametime % 30 == 0 && isRecipientOfHelp( blob, blob, "help show" )) {
			Done( "done help show", blob.getName() );
		}
	}



								// GATHER 
	if (gametime % 16 == 0)
	{
		renderHelps.clear();

		// seated

		if (blob.isAttached())
		{
			AttachmentPoint@ gunner = blob.getAttachments().getAttachmentPointByName("GUNNER");	 
			if (gunner !is null && gunner.getOccupied() !is null && shouldDraw( blob, gunner.getOccupied(), "help GUNNER action" )) {
				renderHelps.push_back( getHelpText( gunner.getOccupied(), "help GUNNER action") );
			}

			AttachmentPoint@ vehicle = blob.getAttachments().getAttachmentPointByName("DRIVER");	 
			if (vehicle !is null && vehicle.getOccupied() !is null && shouldDraw( blob, vehicle.getOccupied(), "help DRIVER movement" )) {
				renderHelps.push_back( getHelpText( vehicle.getOccupied(), "help DRIVER movement") );
			}
		}
		else
		{	  						 
			// near	  

			if (map !is null && map.getBlobsInRadius( blob.getPosition(), blob.getRadius() + HELP_DISTANCE, @blobsInRadius )) 
			{
				for (uint i = 0; i < blobsInRadius.length; i++)
				{
					CBlob @b = blobsInRadius[i]; 
					if (b !is blob && !wasAlreadyInList(blobsInRadius, i, b) ) 
					{
						if (!b.isAttached() 
							&& !b.hasTag("flesh") ) // HACK
						{
							HelpText[]@ helps = getHelps( b );
							if (helps !is null)
							{
								for (uint i = 0; i < helps.length; i++)
								{
									HelpText@ ht = helps[i];
									if ( ht.name != "help movement" && ht.name != "help activate" && ht.name != "help throw" && ht.name != "help rotate" && ht.name != "help GUNNER action"  && ht.name != "help DRIVER movement" 	 //HACK:
										&& shouldDraw( blob, b, ht ) )
									{
										renderHelps.push_back( ht );
									}
								}
							}
						}  
					}
				}
			}

			// inventory

			for (int i = 0; i < inv.getItemsCount(); i++)
			{
				CBlob @b = inv.getItem(i);	
				if (shouldDraw( blob, b, "help activate" )) {
					renderHelps.push_back( getHelpText( b, "help activate") );
				}

				if (shouldDraw( blob, b, "help switch" )) {
					renderHelps.push_back( getHelpText( b, "help switch") );
				}
			}

			//carry 

			if (carried !is null)
			{
				if (shouldDraw( blob, carried, "help activate" ) && !carried.hasTag("activated")) {
					renderHelps.push_back( getHelpText( carried, "help activate") );
				}

				if (shouldDraw( blob, carried, "help throw" ) && carried.hasTag("activated")) {
					renderHelps.push_back( getHelpText( carried, "help throw") );
				}

				if (shouldDraw( blob, carried, "help rotate" ) ) {
					renderHelps.push_back( getHelpText( carried, "help rotate") );
				}

				if (shouldDraw( blob, carried, "help use carried" ) ) {
					renderHelps.push_back( getHelpText( carried, "help use carried") );
				}
			}


		// general - self


			HelpText[]@ helps = getHelps( blob );
			if (helps !is null)
			{
				for (uint i = 0; i < helps.length; i++)
				{
					HelpText@ ht = helps[i];
					if (((ht.name != "help throw" && ht.name != "help putback") || (carried !is null && !carried.hasTag("temp blob") && !carried.hasTag("activated"))) 
						&& shouldDraw( blob, blob, ht ) ) {
							renderHelps.push_back( ht );
					}
				}
			}
		}
	}

	// SAVE

	if (gametime - lastSaveTime > 300)
	{
		done.saveFile("../Cache/HelpDone.cfg");		
		lastSaveTime = gametime;
	}
}

bool wasAlreadyInList( CBlob@[] blobs, uint index, CBlob@ blob )
{
	const string name = blob.getName();
	for (uint i = 0; i < index; i++)
	{
		CBlob @b = blobs[i]; 
		if (name == b.getName())
			return true;
	}
	return false;
}

void onRender( CSprite@ this )
{			
	if (g_videorecording)
		return;
	CBlob@ blob = this.getBlob();
	if (u_showtutorial)
	{
		Vec2f offset( 52.0f, getDriver().getScreenHeight() - 68.0f);
		int count = 0;

		// render helps

		for (uint i = 0; i < renderHelps.size(); i++)
		{
			offset = DrawHelp( blob, renderHelps[i], offset );
		}												

		// draw item captions

		{						 
			if (!getHUD().hasButtons() && !getHUD().hasMenus() &&
				!blob.isKeyPressed(key_left) && !blob.isKeyPressed(key_right) &&
				!blob.isKeyPressed(key_up) && !blob.isKeyPressed(key_action1) &&
				!blob.isKeyPressed(key_down) && !blob.isKeyPressed(key_action2) &&
				!blob.isKeyPressed(key_pickup) && !blob.isKeyPressed(key_inventory)
				)
			{
				CBlob@ mouseBlob = getMap().getBlobAtPosition( blob.getAimPos() );
				if (mouseBlob !is null && (!mouseBlob.hasTag("player") || mouseBlob.hasTag("migrant")))
				{
					GUI::DrawText( mouseBlob.getInventoryName(), mouseBlob.getScreenPos() + Vec2f(-mouseBlob.getWidth(), mouseBlob.getHeight() + 16.0f), color_white );
					//	mouseBlob.RenderForHUD( RenderStyle::outline_front );
				}
			}
		}  
			 
	}
}

Vec2f DrawHelpText( const string &in text, Vec2f offset, f32 donePercent, const bool drawBackground = false )
{
	if (text.size() == 0)
		return Vec2f_zero;
	//Vec2f pos = this.getScreenPos();
	Vec2f pos = offset;
	//f32 y = Maths::Max( 200, int(pos.y) );	
	f32 y = pos.y;
	Vec2f dim;
	GUI::GetTextDimensions( text, dim );
	Vec2f ul = Vec2f(pos.x - 50, y - 18.0f);
	Vec2f lr = Vec2f(pos.x + 180.0f, y + 18.0f);
	if (drawBackground)
	{
		GUI::DrawProgressBar( ul, lr, donePercent );
	}	 
	GUI::DrawText( text, ul + Vec2f(5.0f, 6.0f), lr, color_white, false, false );
	return dim;
}

Vec2f DrawHelp( CBlob@ this, HelpText @ht, Vec2f offset)
{			  
	if (offset.y < 500.f)
		return offset; // no drawing

	if (ht !is null) 
	{
		const bool recipient = isRecipientOfHelp( this, ht );
		ht.drawSize = DrawHelpText( recipient ? ht.text : ht.altText, Vec2f( offset.x * ht.fadeOut, offset.y ), 0.0f, true );	// 1.0f - (ht.reduceAfterTimes == 0 ? 0.0f : float(ht.usedCount)/float(ht.reduceAfterTimes))
		if (recipient || ht.altText.size() > 0) {
			offset.y -= 50.0f;
		}
		return offset;
	}	 
	return offset;
}

bool isRecipientOfHelp( CBlob@ this, HelpText@ ht )
{
	if (ht is null)
		return false;
	const string name = this.getName();
			//printf("name " + name + " ht.recipient " + ht.recipient );
	return (ht.recipient.size() == 0 || ht.recipient == name);
}

bool isRecipientOfHelp( CBlob@ this, CBlob@ b, const string &in name )
{
	HelpText @ht = getHelpTextWithRecipient( b, name, this.getName() );
	if (ht !is null)
	{
		return isRecipientOfHelp( this, ht );
	}
	return false;
}

bool isInReach( CBlob@ this, CBlob@ blob )
{
	Vec2f col;
	return (!getMap().rayCastSolid( blob.getPosition(), this.getPosition(), col ));
}

bool shouldDraw( CBlob@ this, CBlob@ blob, HelpText@ help )
{
	if (help.fadeOut < -5.0f)
		return false;
	if (isInReach( this, blob ))
	{
		string doneName = blob.getName() + " done " + help.name;
		if (!done.exists(doneName))
			return true;
		help.usedCount = done.read_u32( doneName );
		if (help.usedCount < help.reduceAfterTimes+1)
			return true;
		else
		{
			//if (blob.getTickSinceCreated() < 90) {
			//	help.fadeOut = -10.0f;
			//}
			//else if (help.fadeOut > 0.74f)
			//{
			//	help.fadeOut -= 0.0025f;
			//	return true;
			//}
			//else
			//if (help.fadeOut > 0.33f)
			//{
			//	help.fadeOut *= 1.35f * help.fadeOut;
			//	return true;
			//}
			//else
			//	if (help.fadeOut > -5.0f)
			//	{
			//		help.fadeOut -= 0.1f;
			//		return true;
			//	}
		}
	}

	return false;
}


bool shouldDraw( CBlob@ this, CBlob@ blob, const string &in helpName )
{
	HelpText@ help = getHelpTextWithRecipient(blob, helpName, this.getName());
	if (help is null) {
		return false;
	}

	return shouldDraw( this, blob, help );
}
