#include "stdafx.h"
#include "Macrophage.h"

#include "CellWarsGameManager.h"
#include "Bacterium.h"

const float Macrophage::MAX_BASE_HP = 50;
const float Macrophage::BASE_DAMAGE = 20;
const float Macrophage::ATTACK_DISTANCE = 4;
const float Macrophage::STANDARD_SENSOR_DISTANCE = 6.0f;
const float Macrophage::STANDARD_OWN_MOVEMENT_SPEED = 3.0f;
const float Macrophage::STANDARD_DRIFT_AWAY_DISTANCE = 1.5f;
const int Macrophage::NUM_PARTS = 4;
const int Macrophage::NUM_Tentacles = 100;

Macrophage::Macrophage() : MobileMicrobe(), Damageable(MAX_BASE_HP), macrophageParts(new ParticleActor()), 
	lastFrameLifePercentage(1), attackTentacles(new ParticleActor()), devouringThisBacterium(NULL)
{
	float screenCircumcircleRadius = (theCamera.GetWorldMaxVertex() - 
		theCamera.GetWorldMinVertex()).Length() * 0.5f;

	Vector2 spawnPos(MathUtil::RandomVector(-1, +1));
	spawnPos.Normalize();

	SetPosition(spawnPos * screenCircumcircleRadius);
	MoveTo(spawnPos * (screenCircumcircleRadius * 0.3f), 5);
	SetColor(1,1,1,1);
	ClearSpriteInfo();
	SetSize(3);
	SetName("Macrophage");
	SetSprite("Resources/Images/macrophage.png");
	theWorld.Add(this, LayerEnum::Macrophage);

	macrophageParts->SetPosition(this->GetPosition());
	macrophageParts->SetRotation(this->GetRotation());
	macrophageParts->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
	macrophageParts->SetEndColor(Color(1.0f, 1.0f, 1.0f, 0.0f));
	macrophageParts->SetSize(2);
	macrophageParts->SetSprite("Resources/Images/macrophagePart.png");
	macrophageParts->SetParticlesPerSecond(0);
	macrophageParts->SetMaxParticles(NUM_PARTS);
	macrophageParts->SetParticleLifetime(3);
	macrophageParts->SetSpread(MathUtil::Pi);
	macrophageParts->SetSpeedRange(2.5f, 5.0f);
	macrophageParts->SetGravity(Vector2(0));
	theWorld.Add(macrophageParts, LayerEnum::MacrophageTentacles);

	attackTentacles->SetPosition(this->GetPosition());
	attackTentacles->SetRotation(this->GetRotation());
	attackTentacles->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
	attackTentacles->SetEndColor(Color(1.0f, 1.0f, 1.0f, 0.0f));
	attackTentacles->SetSize(Vector2(1.5f, 2));
	attackTentacles->SetSprite("Resources/Images/macrophageTentacle.png");
	attackTentacles->SetParticlesPerSecond(0);
	attackTentacles->SetMaxParticles(NUM_Tentacles);
	//attackTentacles->SetEndScale(0);
	attackTentacles->SetParticleLifetime(1);
	attackTentacles->SetSpread(MathUtil::Pi * 0.125f);
	attackTentacles->SetSpeedRange(4.5f, 5.0f);
	attackTentacles->SetAttractor(GetPosition());
	attackTentacles->SetAttractorStrength(10);
	attackTentacles->SetGravity(Vector2(0));
	theWorld.Add(attackTentacles, LayerEnum::MacrophageTentacles);

	//std::cout << "Macrophage " << _name << std::endl;
}

Macrophage::~Macrophage()
{
	//std::cout << "~Macrophage " << _name << std::endl;
}

void Macrophage::PreDestroy()
{
	spitOutTargetBacterium();

	theCellWarsGame.addKilledMacrophage();
	theCellWarsGame.removeMacrophageFromGame(this);
	macrophageParts->Destroy();
	attackTentacles->Destroy();
}

void Macrophage::die()
{
	this->Destroy();
}
	
void Macrophage::targetBacteriumDied()
{
	devouringThisBacterium = NULL;
}

void Macrophage::ReceiveMessage(Message *m)
{
	MobileMicrobe::ReceiveMessage(m);
}

void Macrophage::Render()
{
	MobileMicrobe::Render();
}

void Macrophage::Update(float dt)
{
	if (IsDestroyed())
		return;

	MobileMicrobe::Update(dt);

	driftAway();
	respectTheLimits();
	
	attackTentacles->SetParticlesPerSecond(0);

	setTargetBacterium();
	if (devouringThisBacterium)
	{
		moveToAndAttackTargetBacterium(dt);
	}

	float currLifePerc(getLifePercentage());
	float stageThreshold = 1;
	for (int i = 0; i < NUM_PARTS; ++i)
	{
		stageThreshold -= 1 / ((float)NUM_PARTS + 1);
		if (lastFrameLifePercentage >= stageThreshold &&
			currLifePerc < stageThreshold)
		{
			macrophageParts->SpawnAdditionalParticles(1);
		}
	}

	macrophageParts->SetPosition(this->GetPosition());
	macrophageParts->SetRotation(MathUtil::RandomFloat() * MathUtil::Pi * 2);

	//updateHPString(this->GetPosition(), this->GetSize());

	lastFrameLifePercentage = getLifePercentage();

	//updateHPString(this->GetPosition(), this->GetSize());
}

void Macrophage::driftAway()
{
	Macrophage* nearestMac = theCellWarsGame.getNearestMacrophageActor(this);
	
	if (nearestMac)
	{
		Vector2 dist(GetPosition() - nearestMac->GetPosition());
		if (dist.Length() < STANDARD_DRIFT_AWAY_DISTANCE && 
			currentVelocity.Length() < STANDARD_OWN_MOVEMENT_SPEED)
		{
			currentVelocity = Vector2::Normalize(dist);
			currentVelocity *= STANDARD_OWN_MOVEMENT_SPEED;
		}
	}
}

void Macrophage::setTargetBacterium()
{
	spitOutTargetBacterium();
	
	float distToNearestBacterium = 0;

	Bacterium* nearestBacterium = theCellWarsGame.getNearestBacterium(this->GetPosition());

	if (nearestBacterium && !nearestBacterium->isDevoured())
	{
		distToNearestBacterium = (nearestBacterium->GetPosition() - this->GetPosition()).Length();
		if (distToNearestBacterium < STANDARD_SENSOR_DISTANCE)
		{
			devouringThisBacterium = nearestBacterium;
			nearestBacterium->devour(this);
			return;
		}
	}
}

void Macrophage::moveToAndAttackTargetBacterium(float dt)
{
	float distToNearestBacterium = 0;

	if (devouringThisBacterium)
	{
		distToNearestBacterium = (devouringThisBacterium->GetPosition() - this->GetPosition()).Length();
		if (distToNearestBacterium <= STANDARD_SENSOR_DISTANCE && 
			currentVelocity.Length() <= STANDARD_OWN_MOVEMENT_SPEED &&
			distToNearestBacterium > (0.25f * devouringThisBacterium->GetSize().X + 0.25f * this->GetSize().X))
		{
			if (IsMoving())
				MoveTo(this->GetPosition(), 0); // stop moveto
			currentVelocity = (devouringThisBacterium->GetPosition() - this->GetPosition());
			currentVelocity.Normalize();
			currentVelocity *= STANDARD_OWN_MOVEMENT_SPEED;
		}

		if (distToNearestBacterium <= ATTACK_DISTANCE)
		{
			Vector2 targetDir(devouringThisBacterium->GetPosition() - GetPosition());
			targetDir.Normalize();
			float angleToTarget = MathUtil::ToDegrees(MathUtil::AngleFromVector(targetDir));
			SetRotation(angleToTarget);
			Vector2 tentaclePos(GetPosition());
			tentaclePos += (targetDir * GetSize().X * 0.25f);
			attackTentacles->SetAttractor(GetPosition());
			attackTentacles->SetPosition(tentaclePos);
			attackTentacles->SetRotation(GetRotation());
			attackTentacles->SetParticlesPerSecond(NUM_Tentacles / 3);
			devouringThisBacterium->addLifePoints(-BASE_DAMAGE * dt);
		}
	}
	else
		currentVelocity *= 0;
}

void Macrophage::spitOutTargetBacterium()
{
	if (devouringThisBacterium)
	{
		devouringThisBacterium->spitOut();
		devouringThisBacterium = NULL;
	}
}