/******************************************************************************
*******************************************************************************

	Bubble Fight EX
	relminator
	http://rel.betterwebber.com


	Popcorn class


*******************************************************************************
******************************************************************************/

#include "Popcorn.h"

#define MIN_X ( -20 << 12 )
#define MIN_Y ( -18 << 12 )

#define MAX_POPCORNS 16

//------------------------------------------------------------------------------
//	Popcorn Enemy
//------------------------------------------------------------------------------
Popcorn::Popcorn()
{
	Frame = 0;
	Active = false;	
	Hp = 32; 
	DrawMode = EN_NORMAL;
	
}

Popcorn::~Popcorn()
{
}


void Popcorn::Update()
{
	
	Path.Update();
	
	x = Path.GetX();
	y = Path.GetY();
	
	if( x < MIN_X )
	{
		Active = false;
		x = 300 << 12;
		y = 96 << 12;
	}

	Counter++;
	// animate
	if( ( Counter & 1 ) == 0 )
	{
		Frame = (Frame + 1) & 3;
	}

}


void Popcorn::LoadPath( int _sx, int _sy, int _ex, int _ey )
{
	Path.Init( 16 );
	
	Spline::Coord p;
	
	// start
	p.x = _sx;
	p.y = _sy;
	
	// we should use 2 points
	Path.AddPoint( p );
	Path.AddPoint( p );
	
	// randomize for now
	for (int i=0; i < 10; i++)
	{
		p.x = qran_range(0, 255);
		p.y = qran_range(0, 193);
		Path.AddPoint( p );
	}
	
	// close last 2 coords
	p.x = _ex;
	p.y = _ey;
	
	// we should use 2 points
	Path.AddPoint( p );
	Path.AddPoint( p );
	
	Path.SetSpeed(qran_range(16,32));
	Path.SetT(0);
	
}
	
//------------------------------------------------------------------------------
//	Popcorn Container
//------------------------------------------------------------------------------
//--------------------------------------
//	Ctor and Dtor
//--------------------------------------
PopcornContainer::PopcornContainer()
{
}
	
PopcornContainer::~PopcornContainer()
{
	Popcorns.clear();				// clear the bullets
}


void PopcornContainer::Init( int Palette, glImage* const Sprites )
{
	ColorTable = Palette;		// init needed data for drawing
	Images = Sprites;
	Popcorns.resize( MAX_POPCORNS/2 );			// 1/2 of max (speed of iteration)
	Popcorns.reserve( MAX_POPCORNS );		// reserve max for speed.  No need to do this for enemies
}

//--------------------------------------
//	Virtual Functions
//--------------------------------------
void PopcornContainer::UpdateEntities()
{
	
	std::vector<Popcorn>::iterator iter;
	for( iter = Popcorns.begin(); iter != Popcorns.end(); ++iter )
	{
		if( iter->Active )
			iter->Update();
	}
	
}

void PopcornContainer::DrawEntities()
{
	
	glColorTable( GL_RGB16, ColorTable );
	numEntities = 0;
	std::vector<Popcorn>::iterator iter;
	for( iter = Popcorns.begin(); iter != Popcorns.end(); ++iter )
	{
		if( iter->Active )
		{
			numEntities++;
			if( (iter->DrawMode == EN_WHITE) )
			{
				iter->DrawMode = EN_NORMAL;
				glColorTable( GL_RGB256, Palettes::Instance()->Red() );
				glSprite( (iter->x >> 12) - 19, (iter->y >> 12) - 16, 
					      GL_FLIP_NONE, &Images[iter->Frame+4] 
					    );
				glColorTable( GL_RGB16, ColorTable );
	
			}
			else
			{
				glSprite( (iter->x >> 12) - 19, (iter->y >> 12) - 16, 
						  GL_FLIP_NONE, &Images[iter->Frame+4] 
					    );
			}
			
		}
	}
	
}

bool PopcornContainer::Collide( StarFighter &Star )
{
	std::vector<Popcorn>::iterator iter;
	for( iter = Popcorns.begin(); iter != Popcorns.end(); ++iter )
	{
		if( iter->Active )
		{
			int rad2 = 16 * 16;
			int cx = (iter->x >> 12) - (Star.x >> 12);
			int cy = (iter->y >> 12) - (Star.y >> 12);
			if( ( (cx * cx) + (cy * cy) ) < (rad2 * (1+Star.IsBursting())) )
			{
				if( Star.IsBursting() )
				{
					iter->Hp--;
					if( (iter->Hp & 3) == 0 ) Sound::Instance()->PlaySFX(E_SFX_HIT);
					if( iter->Hp < 0 )
					{
						iter->Active = false;
						Star.Score += 130;
						Sound::Instance()->PlaySFX(E_SFX_SMALLEXP);
						// Add some nice explosions
						Explosion::Instance()->Spawn( iter->x >> 12,
													  iter->y >> 12,
													   0,
													   0,
													   EX_MEDIUM_2
													 );
							
						for( int i = 0; i < 4; i++ )
						{	
							s32 dx = cosLerp(i * BRAD_PI / 2);
							s32 dy = sinLerp(i * BRAD_PI / 2);
							Explosion::Instance()->Spawn( iter->x >> 12,
													  iter->y >> 12,
													   dx,
													   dy,
													   EX_SMALL_3
													 );
							
						}
						iter->x = 600 <<12;
						iter->y = 96 << 12;
						
					}
					if( iter->DrawMode == EN_NORMAL )
					{
						if( (iter->Counter & 1) ) iter->DrawMode = EN_WHITE;
					}
				}
				else
				{
					// kill star
					if( !Star.IsInvincible() ) Star.Kill();
				}
				return true;
			}
		}
	}
	return false;
}



void PopcornContainer::KillAllEntities()
{
	std::vector<Popcorn>::iterator iter;
	for( iter = Popcorns.begin(); iter != Popcorns.end(); ++iter )
	{
		if( iter->Active )
		{
			iter->Active = false;
			iter->x = 600 << 12;
			iter->y = 96 << 12;
		}
	}
	
}

//--------------------------------------
//	Non-Virtual Functions
//--------------------------------------
void PopcornContainer::Spawn( int _x, int _y, s32 speed, int _radius )
{
	
	bool SlotFull = true;      		// value to check if all the slots are occupied
	
	std::vector<Popcorn>::iterator iter;
	for( iter = Popcorns.begin(); iter != Popcorns.end(); ++iter )
	{
		if( !iter->Active )		// insert a bullet on a free slot
		{

			iter->Active = true;
			iter->Frame = 0;
			iter->Counter = 0;
			iter->Hp = 32;
			iter->LoadPath( 300, 96, -300, 96 );
			SlotFull = false;			// there's a free slot so we dont execute the code below
			break;
		
		}
	}
	
	// All the slots are full
	// Only push back a bullet if the slot is full and we have less than numbullets
	if( SlotFull && (Popcorns.size() < MAX_POPCORNS) )
	{
		Popcorn popcorn;
		popcorn.Active = true;
		popcorn.Frame = 0;
		popcorn.Counter = 0;
		popcorn.Hp = 32;
		popcorn.LoadPath( 300, 96, -300, 96 );
		Popcorns.push_back(popcorn);
	}
	
}

