//	Bee.cpp - Class representing a bee.
//  ----------------------------------------------------------------------------
//	This file is part of 'NiallsAVLib', base code for any kind of audiovisual
//	apps.
//	Copyright (C) 2012  Niall Moody
//	
//	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/>.
//	----------------------------------------------------------------------------

#include "drawing/Drawer.h"
#include "GamePlayState.h"
#include "MiscHelper.h"
#include "Random.h"
#include "Tank.h"
#include "Bee.h"

//------------------------------------------------------------------------------
Bee::Bee(const TwoFloats& centrePos, const ThreeFloats& col):
NPC(L"Bee"),
centrePosition(centrePos),
colour(col),
wingCount(1+Random::getGlobal().getRandomInt(5)),
dead(false)
{
	float angle = Random::getGlobal().getRandomFloat() * 2.0f * NIALL_PI;
	float radius = Random::getGlobal().getRandomFloat() * 38.0f;

	position = centrePos;
	position.x += sinf(angle) * radius;
	position.y += cosf(angle) * radius;

	direction.x = (Random::getGlobal().getRandomFloat() * 2.0f) - 1.0f;
	direction.y = (Random::getGlobal().getRandomFloat() * 2.0f) - 1.0f;
	direction = direction.normal();

	desiredDirection.x = (Random::getGlobal().getRandomFloat() * 2.0f) - 1.0f;
	desiredDirection.y = (Random::getGlobal().getRandomFloat() * 2.0f) - 1.0f;
	desiredDirection = desiredDirection.normal();
}

//------------------------------------------------------------------------------
Bee::~Bee()
{

}

//------------------------------------------------------------------------------
void Bee::update(GamePlayState& state)
{
	int i;
	float angle;
	TwoFloats tempDir;

	//If we're chasing a tank, try and move towards it.
	if(targetTank)
	{
		//If the tank's out of range, abandon the chase.
		if(position.getDistance(targetTank->getPosition()) > 96.0f)
			targetTank.reset();
		else
		{
			direction += (desiredDirection-direction) * 0.01f;
			direction = direction.normal();

			direction = desiredDirection;

			tempDir = (targetTank->getPosition() - position).normal();
			angle = tempDir.getAngle();
			desiredDirection.x = sinf(angle);
			desiredDirection.y = cosf(angle);
		}
	}
	else
	{
		//If there is a tank nearby, target it.
		for(i=0;i<state.getNumTanks();++i)
		{
			shared_ptr<Tank>& t(state.getTank(i));

			if(t->getColour() != colour)
			{
				if(position.getDistance(t->getPosition()) <= 96.0f)
				{
					targetTank = t;

					direction = desiredDirection;

					tempDir = (targetTank->getPosition() - position).normal();
					angle = tempDir.getAngle();
					desiredDirection.x = sinf(angle);
					desiredDirection.y = cosf(angle);

					break;
				}
			}
		}

		//If the bee has moved too far away from the centre position, point it
		//back towards it.
		if(centrePosition.getDistance(position) > 48.0f)
			desiredDirection = (centrePosition-position).normal();

		direction += (desiredDirection-direction) * 0.1f;
		direction = direction.normal();

		//If direction has converged on desiredDirection, reset desiredDirection.
		if(direction.getDistance(desiredDirection) < 0.01f)
		{
			desiredDirection.x = (Random::getGlobal().getRandomFloat() * 2.0f) - 1.0f;
			desiredDirection.y = (Random::getGlobal().getRandomFloat() * 2.0f) - 1.0f;
			desiredDirection = desiredDirection.normal();
		}
	}

	//Move the bee along its direction vector.
	if(targetTank)
		position += direction * 1.75f;
	else
		position += direction;

	//Update the bee's wings animation.
	--wingCount;
	if(!wingCount)
		wingCount = 5;
}

//------------------------------------------------------------------------------
void Bee::draw(shared_ptr<Drawer>& d, float timestepInterp)
{
	std::wstring image;
	TwoFloats pivot(0.0f, 4.0f);
	TwoFloats tempPos(position.x, position.y-4.0f);
	TwoFloats tempDir(direction.x, -direction.y);
	const float angle(tempDir.getAngle());

	if(wingCount > 2)
	{
		image = L"Bee0";
		tempPos.x -= 6.5f;
		pivot.x = 6.5f;
	}
	else
	{
		image = L"Bee1";
		tempPos.x -= 3.0f;
		pivot.x = 3.0f;
	}

	d->drawRotImage(image,
					tempPos,
					angle,
					pivot,
					1.0f,
					colour);
}

//------------------------------------------------------------------------------
bool Bee::interestedInCollisionsWith(const std::wstring& entity) const
{
	bool retval = false;

	if((entity == L"Tank") || (entity == L"Bullet") || (entity == L"Zombie"))
		retval = true;

	return retval;
}

//------------------------------------------------------------------------------
bool Bee::collide(const shared_ptr<Collidable>& other, GamePlayState& state)
{
	bool retval = false;
	const std::wstring& n(other->getName());

	if(n == L"Tank")
	{
		shared_ptr<Tank> t(dynamic_pointer_cast<Tank>(other));

		if(t)
		{
			if(t->getColour() != colour)
			{
				retval = true;
				dead = true;
			}
		}
	}
	else if(n == L"Bullet")
	{
		retval = true;
		dead = true;
	}

	return false;
}
