//	Turret.cpp - A stationary turret which fires at nearby players/npcs of a
//			     different colour.
//  ----------------------------------------------------------------------------
//	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 "Turret.h"
#include "Random.h"
#include "Tank.h"

//------------------------------------------------------------------------------
Turret::Turret(const TwoFloats& pos, const ThreeFloats& col, bool dec):
NPC(L"Turret"),
position(pos),
colour(col),
december(dec),
armour(1.0f),
searchRadius(384.0f),
angle(Random::getGlobal().getRandomFloat() * 2.0f * NIALL_PI),
angleCount(0),
fireCount(0)
{

}

//------------------------------------------------------------------------------
Turret::~Turret()
{

}

//------------------------------------------------------------------------------
void Turret::update(GamePlayState& state)
{
	int i;
	float tempAngle;

	if(targetTank)
	{
		if(targetTank->getDead())
			targetTank.reset();
	}
	if(targetNpc)
	{
		if(targetNpc->getDead())
			targetNpc.reset();
	}

	if(angleCount <= 0)
	{
		float tempDist;
		const float searchSquared = searchRadius*searchRadius;
		int numTanks = state.getNumTanks();
		int numNpcs = state.getNumNpcs();
		int tank = -1;
		float tankDist = 1000000.0f;
		int npc = -1;
		float npcDist = 1000000.0f;

		targetTank.reset();
		targetNpc.reset();

		for(i=0;i<numTanks;++i)
		{
			tempDist = position.getDistanceSquared(state.getTank(i)->getPosition());

			if((tempDist < searchSquared) && (tempDist < tankDist))
			{
				if(state.getTank(i)->getColour() != colour)
				{
					tank = i;
					tankDist = tempDist;
				}
			}
		}
		for(i=0;i<numNpcs;++i)
		{
			tempDist = position.getDistanceSquared(state.getNpc(i)->getPosition());

			if((tempDist < searchSquared) && (tempDist < tankDist))
			{
				if(state.getNpc(i)->getColour() != colour)
				{
					npc = i;
					npcDist = tempDist;
				}
			}
		}

		if((tank > -1) && (npc > -1))
		{
			if(tankDist < npcDist)
				targetTank = state.getTank(tank);
			else
				targetNpc = state.getNpc(npc);
			angleCount = 30;
		}
		else if(tank > -1)
		{
			targetTank = state.getTank(tank);
			angleCount = 30;
		}
		else if(npc > -1)
		{
			targetNpc = state.getNpc(npc);
			angleCount = 30;
		}
	}
	else
		--angleCount;

	if(targetTank)
	{
		tempAngle = position.getAngle(targetTank->getPosition());

		if(fabsf(tempAngle-angle) > NIALL_PI)
		{
			if(tempAngle > angle)
			{
				while(fabsf(tempAngle-angle) > NIALL_PI)
					tempAngle -= 2.0f*NIALL_PI;
			}
			else
			{
				while(fabsf(tempAngle-angle) > NIALL_PI)
					tempAngle += 2.0f*NIALL_PI;
			}
		}

		angle += (tempAngle-angle) * 0.1f;
		if(fabsf(tempAngle-angle) < 0.05f)
			angle = tempAngle;
	}
	else if(targetNpc)
	{
		tempAngle = position.getAngle(targetNpc->getPosition());

		angle += (tempAngle-angle) * 0.1f;
		if(fabsf(tempAngle-angle) < 0.05f)
			angle = tempAngle;
	}

	--fireCount;

	if(targetTank || targetNpc)
	{
		if(!fireCount)
		{
			TwoFloats dir(sinf(angle), cosf(angle));

			state.firePlainBullet(position+(dir*30.0f), dir, colour, L"Turret");
		}
	}

	if(fireCount <= 0)
		fireCount = 90;
}

//------------------------------------------------------------------------------
void Turret::draw(shared_ptr<Drawer>& d, float timestepInterp)
{
	if(december)
	{
		d->drawImage(L"Snowman", TwoFloats(position.x-18.0f, position.y-22.5f));
		d->drawImage(L"SnowmanHat",
					 TwoFloats(position.x-18.0f, position.y-22.5f),
					 1.0f,
					 colour);
		d->drawImage(L"SnowmanBobble",
					 TwoFloats(position.x-18.0f, position.y-22.5f));
	}
	else
	{
		TwoFloats tempPos(sinf(angle), -cosf(angle));
		float drawAngle(tempPos.getAngle());

		d->drawImage(L"TurretBaseBottom",
					 position-12.0f,
					 1.0f,
					 0.1875f);
		d->drawImage(L"TurretBaseTop",
					 position-14.0f,
					 1.0f,
					 colour);
		d->drawRotImage(L"TurretCannonBottom",
						position-16.0f,
						drawAngle,
						16.0f,
						1.0f,
						0.1875f);
		d->drawRotImage(L"TurretCannonTop",
						position-18.0f,
						drawAngle,
						18.0f,
						1.0f,
						colour);
	}
}

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

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

	return retval;
}

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

	if(n == L"Bullet")
		armour -= 0.2f;
	else if(n == L"Shockwave")
		armour -= 0.05f;

	return true;
}
