//Copyright (C) 2007 SiegeLord
//See ReadMe.txt and License.txt for copying information

#include "particles.h"

////////////////////////////////////////////
//		BasicParticleObject Stuff
////////////////////////////////////////////

SParticleHolder* InitParticleHolder(SParticleHolder* holder, SObject* parent)
{
	InitObject((SObject*)holder, parent);
	return holder;
}

void SParticleHolder::UpdateBuffers()
{
	int index = 0;
	int index2 = 0;
	float half_w = bmp->w / 2;
	float half_h = bmp->h / 2;
	int n = 0;
	FOR1(num_particles)
	{
		index2 = ii * 4;

		//not exactly sure why we need to reset the colors
		colors[index2 + 0] = 0;
		colors[index2 + 1] = 0;
		colors[index2 + 2] = 0;
		colors[index2 + 3] = 0;

		if(particles[ii].life > 0)
		{
			index = n * 12;
			index2 = n * 4;
			vertices[index +  0] = particles[ii].position.x - half_w;
			vertices[index +  1] = particles[ii].position.y - half_h;
			vertices[index +  2] = -10;
			colors[index2 + 0] = particles[ii].color;

			vertices[index +  3] = particles[ii].position.x + half_w;
			vertices[index +  4] = particles[ii].position.y - half_h;
			vertices[index +  5] = -10;
			colors[index2 + 1] = particles[ii].color;

			vertices[index +  6] = particles[ii].position.x + half_w;
			vertices[index +  7] = particles[ii].position.y + half_h;
			vertices[index +  8] = -10;
			colors[index2 + 2] = particles[ii].color;

			vertices[index +  9] = particles[ii].position.x - half_w;
			vertices[index + 10] = particles[ii].position.y + half_h;
			vertices[index + 11] = -10;
			colors[index2 + 3] = particles[ii].color;
			n++;
		}
	}
	num_alive_particles = n;
}

void SParticleHolder::CreateBuffers()
{
	colors = new int[num_particles * 4];
	vertices = new float[num_particles * 3 * 4];
	tcoords = new float[num_particles * 2 * 4];

	memset(colors, 0, sizeof(int) * num_particles * 4);
	memset(vertices, 0, sizeof(float) * num_particles * 3 * 4);
	memset(tcoords, 0, sizeof(float) * num_particles * 2 * 4);

	particles = new SParticle[num_particles];

	//we set up the the tcoords
	int index = 0;
	FOR1(num_particles)
	{
		index = ii * 8;

		tcoords[index + 0] = 0.0f;
		tcoords[index + 1] = 1.0f;

		//cent.vertices.push_back(vector3di(x, y, depth));

		tcoords[index + 2] = 1.0f;
		tcoords[index + 3] = 1.0f;
		//cent.vertices.push_back(vector3di(x + bmp->w, y, depth));

		tcoords[index + 4] = 1.0f;
		tcoords[index + 5] = 0.0f;
		//cent.vertices.push_back(vector3di(x + bmp->w, y + bmp->h, depth));

		tcoords[index + 6] = 0.0f;
		tcoords[index + 7] = 0.0f;
		//cent.vertices.push_back(vector3di(x, y + bmp->h, depth));
	}
}

SParticleHolder::~SParticleHolder()
{
	delete[] particles;
	delete[] tcoords;
	delete[] vertices;
	delete[] colors;
}

////////////////////////////////////////////
//		SmokeParticle Stuff
////////////////////////////////////////////

int SSmokeParticleHolder::Handle()
{
	int num_reset = 0;

	FOR1(num_particles)
	{
		SParticle* part = &(particles[ii]);
		if(part->life <= 0 && num_reset < throttle * g_fDelta)//we reset it
		{
			num_reset++;
			part->life = Rand(min_life, max_life);

			part->position = GetGlobalPosition();
			part->velocity.y = -Rand() * random_vel_y;
			part->velocity.x = Rand(-random_vel_x, random_vel_x);
		}
		else
		{
			part->life -= g_fDelta;
			part->velocity.y += acceleration * g_fDelta;
			part->velocity.y *= powf(dampening, g_fDelta);
			part->velocity.x *= powf(dampening, g_fDelta);

			part->position = part->position + part->velocity * g_fDelta;
		}

		float factor = part->life / max_life;
		if(factor < 0)
			factor = 0;
		part->color = BlendColors(0x00000000, 0xffffffff, factor);
	}


	UpdateBuffers();
	return 0;
}

void SSmokeParticleHolder::Draw()
{
	//SetModelMatrix(net_transform);
	DrawModeAdd();

	DrawQuadBuffer(bmp, num_alive_particles, vertices, tcoords, colors);

	DrawModeSolid();

	//SetModelMatrix(g_trIdentity);
}

SSmokeParticleHolder* CreateSmokeParticle(SObject* parent, SBitmap* bmp)
{
	SSmokeParticleHolder* hold = new SSmokeParticleHolder(100);

	InitParticleHolder(hold, parent);

	hold->bmp = bmp;
	hold->restart = true;

	hold->dampening = 0.75;
	hold->random_vel_x = 15.0f;
	hold->random_vel_y = 15.0f;
	hold->max_life = 2.0f;
	hold->min_life = 0.5f;
	hold->acceleration = -40;
	hold->throttle = 150;

	hold->CreateBuffers();

	return hold;
}

void SAuraParticleHolder::Draw()
{
	//SetModelMatrix(net_transform);
	DrawModeAdd();
	DrawQuadBuffer(bmp, num_alive_particles, vertices, tcoords, colors);

	DrawModeSolid();

	//SetModelMatrix(g_trIdentity);
}

int SAuraParticleHolder::Handle()
{
	int num_reset = 0;

	FOR1(num_particles)
	{
		SParticle* part = &(particles[ii]);
		if(part->life <= 0 && num_reset < throttle * g_fDelta)//we reset it
		{
			num_reset++;

			part->life = Rand(min_life, max_life);

			float theta = Rand() * 2 * AL_PI;

			//vector2d temp;
			//VecAssignCoords(&temp, radius * cosf(theta), radius * sinf(theta));
			//VecAssign(&part->position, &GetObjectPosition(obj));
			//part->position = GetObjectPosition(obj);
			//VecAdd(&part->position, &temp);
			part->position = GetGlobalPosition() + vector2d(radius * cosf(theta), radius * sinf(theta));

			float vel = Rand(min_speed, max_speed);

			part->velocity.x = radius / radius * cosf(theta) * vel;
			part->velocity.y = radius / radius * sinf(theta) * vel;
		}
		else
		{
			part->life -= g_fDelta;

			part->velocity.y += acceleration * g_fDelta;
			vector2d temp = part->velocity;
			//VecAssign(&part->velocity, &temp);

			//VecMultiply(&temp, g_fDelta);
			//VecAdd(&part->position, &temp);
			part->position = part->position + part->velocity * g_fDelta;
		}

		float factor = part->life / max_life;
		if(factor < 0)
			factor = 0;
		part->color = BlendColors(0x00000000, 0xffffffff, factor);
	}

	UpdateBuffers();
	//check if particles have a life of 0
	//respawn them then
	//update buffers
	return 0;
}

SAuraParticleHolder* CreateAuraParticle(SObject* parent, SBitmap* bmp)
{
	SAuraParticleHolder* hold = new SAuraParticleHolder(500);

	InitParticleHolder(hold, parent);

	hold->bmp = bmp;
	hold->restart = true;

	hold->radius = 40;
	hold->acceleration = -250;
	hold->min_speed = 80;
	hold->max_speed = 150;
	hold->dampening = 0.75;
	hold->max_life = .5;
	hold->min_life = .25;
	hold->throttle = 150;

	hold->CreateBuffers();

	return hold;
}
