#include "empire.h"
#include "logic.h"  //needed for P_CASH

void create_particle(int x, int y, int type);
void create_particle(int x, int y, int type, int color, string text);

list<_particle> p_effects;

void _particle::create(int _x, int _y, particletype _type, int _color, string _text)
{
	int a, b, z;
	x = float(_x);
	y = float(_y);
	type = _type;
	a = rand()%2;
	if (a == 0) a = -1;
	b = rand()%2;
	if (b == 0) b = -1;
	color = _color;
	text = _text;
	
	switch(type)
	{
		case P_FLAME:
			xv = (float(rand()%30) / 10) * float(a);
			yv = (float(rand()%30) / 10) * float(b);
			xa = 0;
			ya = 0;
			life = 8;
			break;
		case P_DUST:
			xv = (float(rand()%5) / 10) * float(a);
			yv = (float(rand()%5) / 10) * float(b) - 0.5;
			xa = 0;
			ya = 0;
			life = 10;
			break;
		case P_SMOKE:
			xv = (float(rand()%5) / 10) * float(a);
			yv = (float(rand()%2) / 10) * float(a);
			xa = 0;
			ya = -0.02;
			life = 25;
			break;
		case P_AIRTRAIL:
			xv = (float(rand()%6) / 10) * float(a);
			yv = (float(rand()%6) / 10) * float(b);
			xa = 0;
			ya = 0;
			life = 10;
			break;
		case P_SEATRAIL:
			xv = (float(rand()%5) / 10) * float(a);
			yv = (float(rand()%5) / 10) * float(b);
			xa = 0;
			ya = 0;
			life = 30;
			break;
		case P_HORIZONTAL:
			xv = (3.0 + float(rand()%12)) * float(a);
			yv = 0;
			xa = 0;
			ya = 0;
			life = 20;
			break;
		case P_FADETEXT:
			xv = 0;
			yv = 0;
			xa = 0;
			ya = 0;
			life = 75;
			break;
		case P_SHOCKWAVE:
			xv = 0;
			yv = 0;
			xa = 0;
			ya = 0;
			life = 25;
			break;
		case P_TELEPORT:
			xv = 0;
			yv = 0;
			xa = 0;
			ya = 0;
			life = 16;
			break;
		case P_SHOTHIT:
			xv = 0;
			yv = 0;
			xa = 0;
			ya = 0;
			life = 6;
			break;
		case P_REPAIR:
			xv = 0;
			yv = -1.0;
			xa = 0;
			ya = 0;
			life = 50;
			break;
		case P_CASH:
			xv = 0;
			yv = -1.5;
			xa = 0;
			ya = 0;
			life = 50;
			break;
		case P_FIRE:
			z = rand()%3;
			if (z == 0) color = RED;
			else if (z == 1) color = ORANGE;
			else color = YELLOW;
			xv = float(rand()%20) / 10 - 1;
			yv = float(rand()%10) / 10 + 0.25;
			xa = 0;
			ya = -0.3 - float(rand()%10) / 10;
			life = 5;
			break;
		case P_NUKEBOOM:
			xv = 0;
			yv = 0;
			xa = 0;
			ya = 0;
			life = 52;
			break;
		case P_QUADSPIRAL:
			xv = 0;
			yv = 0;
			xa = 0;
			ya = 0;
			life = 50;
			break;
		case P_LOGO:
			xv = float(rand()%20 + 10) / 10.0 * float(a);
			yv = float(rand()%20 + 10) / 10.0 * float(b);
			xa = 0;
			ya = 0;
			life = 100;
			break;
		case P_SHIELDWAVE:
			xv = 0;
			yv = 0;
			xa = 0;
			ya = 0;
			life = MAP_TILE_SIZE * SHIELD_RADIUS;
			break;
		case P_SHIELDSPARK:
			xv = float(rand()%20) / 10.0 * ((rand()%2 == 0) ? 1 : -1);
			yv = float(rand()%20) / 10.0 * ((rand()%2 == 0) ? 1 : -1) - 3.5;
			xa = 0;
			ya = 0.5;
			life = 10;
			break;
		case P_SHIELDGLOW:
			xv = 0;
			yv = -0.2;
			xa = 0;
			ya = 0;
			life = 20;
			break;
	}
	exists = true;
}

void _particle::move()
{
	xv += xa;
	x += xv;
	yv += ya;
	y += yv;
	life--;
	if (life <= 0)
	{
		exists = false;
	}
}

void _particle::draw()
{
	int screenx = int(x) - (worldmap.camera.get_scroll_x() * MAP_TILE_SIZE) + worldmap.camera.get_offset_x();
	int screeny = int(y) - (worldmap.camera.get_scroll_y() * MAP_TILE_SIZE) + worldmap.camera.get_offset_y();
	int r, t1, t2;
	float ang;

	if (((screenx > -20) && (screenx < global.screen_width) && (screeny > -10) && (screeny < global.screen_height)) || (type == P_FADETEXT) || (type == P_LOGO))
	{
		switch(type)
		{
			case P_FLAME:
				r = (10 - life) / 5;
				buffer_circlefill(screenx, screeny, r, color);
				break;
			case P_DUST:
				r = (10 - life) / 5;
				buffer_circlefill(screenx, screeny, float(r + 1), LGREY, float(life) * 0.3);
				break;
			case P_SMOKE:
				r = (25 - life) / 5;
				buffer_circlefill(screenx, screeny, r, color, float(life) / 15.0);
				break;
			case P_AIRTRAIL:
				buffer_putpixel(screenx, screeny, WHITE, 0.6);
				break;
			case P_SEATRAIL:
				buffer_putpixel(screenx, screeny, makecol(170, 170, 255));
				break;
			case P_HORIZONTAL:
				buffer_putpixel(screenx, screeny, color);
				if (life % 5 == 0)
				{
					buffer_putpixel(screenx + 1, screeny, color);
					buffer_putpixel(screenx - 1, screeny, color);
					buffer_putpixel(screenx, screeny + 1, color);
					buffer_putpixel(screenx, screeny - 1, color);
				}
				else
				{
					buffer_putpixel(screenx + 1, screeny + 1, color);
					buffer_putpixel(screenx - 1, screeny + 1, color);
					buffer_putpixel(screenx + 1, screeny - 1, color);
					buffer_putpixel(screenx - 1, screeny - 1, color);
				}
				break;
			case P_FADETEXT:
				buffer_rectrounded(int(x) - 10, int(y) - 8, int(x) + big.Width(text) + 10, int(y) + big.Height(text) + 10, BLACK, float(life) / 75);
				buffer_textout_ex(big, text, int(x), int(y), color, ((float(life) / 50) < 1.0) ? (float(life) / 50) : 1.0);
				break;
			case P_SHOCKWAVE:
				r = (25 - life) * 3;
				buffer_circlefill(screenx, screeny, r, WHITE, float(life) / 25.0);
				break;
			case P_TELEPORT:
				t1 = screenx + MAP_TILE_SIZE / 2;
				t2 = screeny + MAP_TILE_SIZE / 2;
				if (life > 8)
				{
					buffer_rectfill(t1 - (16 - life)*2, 0, t1 + (16 - life)*2, t2, WHITE);
					buffer_circlefill(t1, t2, (16 - life)*2, WHITE);
				}
				else
				{
					buffer_rectfill(t1 - life*2, 0, t1 + life*2, t2, WHITE);
					buffer_circlefill(t1, t2, life*2, WHITE);
				}
				break;
			case P_SHOTHIT:
				buffer_circlefill(screenx, screeny, life, makecol(220 - life * 20, 0, 0), 0.5);
				create_particle(int(x), int(y), P_SMOKE);
				break;
			case P_CASH:
				buffer_textout_ex(big, "$", screenx, screeny, BLACK, (2.0 * float(life)) / 100);
				break;
			case P_REPAIR:
				glb.draw(38, screenx, screeny, (2.0 * float(life)) / 100);
				break;
			case P_FIRE:
				buffer_additive_circlefill(screenx, screeny, 3, color, life / 5.0);
				buffer_putpixel(screenx + rand()%16 - 8, screeny + rand()%16 - 8, color, life / 4.0);
				break;
			case P_NUKEBOOM:
				buffer_rectfill(0, 0, global.screen_width, global.screen_height, WHITE, 1.0 - (float(52 - life) / 52.0));
				buffer_draw_sprite(nukeboom.bmp(26 - (life / 2)), screenx - 112, screeny - 200);
				break;
			case P_QUADSPIRAL:
				ang = life / 18.0;
				buffer_circlefill(screenx + int(life * 0.5 * cos(ang)), screeny + int(life * 0.5 * sin(ang)), 5, color, 0.7);
				ang += AL_PI / 2;
				buffer_circlefill(screenx + int(life * 0.5 * cos(ang)), screeny + int(life * 0.5 * sin(ang)), 5, color, 0.7);
				ang += AL_PI / 2;
				buffer_circlefill(screenx + int(life * 0.5 * cos(ang)), screeny + int(life * 0.5 * sin(ang)), 5, color, 0.7);
				ang += AL_PI / 2;
				buffer_circlefill(screenx + int(life * 0.5 * cos(ang)), screeny + int(life * 0.5 * sin(ang)), 5, color, 0.7);
	
				create_particle(int(x) + rand()%MAP_TILE_SIZE - MAP_TILE_SIZE / 2, int(y) + rand()%MAP_TILE_SIZE - MAP_TILE_SIZE / 2, P_DUST);
				break;
			case P_LOGO:
				if (life > 60)
				{
					glb.draw(40, int(x), int(y), float(100 - life) / 40.0);
				}
				else if (life <= 40)
				{
					glb.draw(40, int(x), int(y), float(life) / 40.0);
				}
				else glb.draw(40, int(x), int(y));
				break;
			case P_SHIELDWAVE:
				{
					const int r = MAP_TILE_SIZE * SHIELD_RADIUS - life;
					buffer_discfill(screenx, screeny, r, r + 4, WHITE, float(MAP_TILE_SIZE * SHIELD_RADIUS - r) / float(MAP_TILE_SIZE * SHIELD_RADIUS));
				}
				break;
			case P_SHIELDSPARK:
				{
					int color;
					int randcol = rand()%3;
					
					if (randcol == 0)
						color = WHITE;
					else if (randcol == 1)
						color = YELLOW;
					else
						color = ORANGE;
					
					buffer_putpixel(screenx, screeny, color, 0.9);
				}
				break;
			case P_SHIELDGLOW:
				buffer_rectfill(screenx, screeny, screenx + 3, screeny + 3, WHITE, 1.0 - (float(life) / 20.0));
				break;
		}
	}
}

void create_particle(int x, int y, particletype type)
{
	if (type == P_SMOKE)
	{
		create_particle(x, y, type, GREY);
	}
	else
	{
		create_particle(x, y, type, WHITE);
	}
}

void create_particle(int x, int y, particletype type, int color, string text)
{
	_particle t;

	t.create(x, y, type, color, text);
	p_effects.push_front(t);
}

void do_particles()
{
	list<_particle>::iterator it = p_effects.begin();

	while (it != p_effects.end())
	{
		if (((*it).type != P_CASH) || (game->state != SCROLLING))
		{  //special case: cash icons don't show when scrolling
			(*it).move();
			(*it).draw();
		}

		if (!(*it).exists)
		{
			it = p_effects.erase(it);
			it--;
		}
		it++;
	}
}

void clear_nonunit_particles()
{
	for (list<_particle>::iterator it = p_effects.begin(); it != p_effects.end(); it++)
	{
		if (it->type == P_SMOKE)
			continue;
		if (it->type == P_SHIELDWAVE)
			continue;
		if (it->type == P_SHIELDSPARK)
			continue;
		if (it->type == P_SHIELDGLOW)
			continue;

		it = p_effects.erase(it);
		it--;
	}
}

void clear_particles()
{
	p_effects.clear();
}
