//#include <math.h>
#include "launcher.h"
#include "pcx.h"
#include "pvrutils.h"

static uint32 txr_flame, txr_flame_flare;

typedef struct {
	float x, y, z, inten, alpha, pad0, pad1, pad2;
} part_t;

#define NUM_PARTS 10

typedef struct {
	int	countdown;
	float	x, y, z;
	float	r, g, b;
	float	vtheta, theta;
	part_t	parts[NUM_PARTS];
} particle_t;

#define NUM_PARTICLES 8
particle_t particles[NUM_PARTICLES];

void img_to_alpha(uint16 *img, int w, int h) {
	register uint32 r, g, b, a, i;
	
	for (i=0; i<w*h; i++) {
		a = ((img[i] & 0x07e0) >> 5) >> 2;
		if (a > 15) a = 15;
		img[i] = (a<<12) | 0xfff;
	}
}

void particle_init_one(particle_t *part, float x, float y, float z) {
	int i;

	part->x = x;
	part->y = y;
	part->z = z;
	part->theta = 0.0f;
	switch((rand() >> 29) & 7) {
	case 0:
		part->r = 1.0f;
		part->g = 0.0f;
		part->b = 0.0f;
		break;
	case 1:
		part->r = 0.0f;
		part->g = 1.0f;
		part->b = 0.0f;
		break;
	case 2:
		part->r = 0.0f;
		part->g = 0.0f;
		part->b = 1.0f;
		break;
	case 3:
		part->r = 1.0f;
		part->g = 1.0f;
		part->b = 0.0f;
		break;
	case 4:
		part->r = 1.0f;
		part->g = 0.0f;
		part->b = 1.0f;
		break;
	case 5:
		part->r = 0.0f;
		part->g = 1.0f;
		part->b = 1.0f;
		break;
	case 6:
		part->r = 0.5f;
		part->g = 0.0f;
		part->b = 1.0f;
		break;
	case 7:
		part->r = 1.0f;
		part->g = 1.0f;
		part->b = 1.0f;
		break;
	}
	for (i=0; i<NUM_PARTS; i++) {
		part->parts[i].x = x;
		part->parts[i].y = y;
		part->parts[i].z = z;
		part->parts[i].inten = 0.0f;
		part->parts[i].alpha = 1.0f;
	}
}

int particle_init() { return 0; }

int particle_reload() {
	Image *img;
	int i;
	float tt;

	txr_flame = ta->txr_allocate(128*128*2);
	txr_flame_flare = ta->txr_allocate(128*128*2);

	img = pcx_load("flame_center.pcx");
	if (img == NULL) {
		printf("can't load flame center image\r\n");
		return -1;
	}
	txr_twiddle_copy(img->pixel_data, img->width, img->height, txr_flame_flare,
		128, 128, 0);
	pcx_free(img);
	img_to_alpha(ta->txr_map(txr_flame), 128, 128);

	img = pcx_load("flame_halo.pcx");
	if (img == NULL) {
		printf("can't load flame halo image\r\n");
		return -1;
	}
	txr_twiddle_copy(img->pixel_data, img->width, img->height, txr_flame,
		128, 128, 0);
	pcx_free(img);
	img_to_alpha(ta->txr_map(txr_flame), 128, 128);

	for (i=0; i<NUM_PARTICLES/2; i++) {
		particle_init_one(&particles[i], 320.0f, 480.0f, 512.0f);
		particles[i].countdown = thd->jiffies() + i * 5;
		particles[i].theta = i * (2*3.1415926f/(NUM_PARTICLES/2));
		particles[i].vtheta = 2*3.1415926f/8.0f;
	}

	for (i=0; i<NUM_PARTICLES/2; i++) {
		particle_init_one(&particles[i+NUM_PARTICLES/2], 320.0f, 480.0f, 512.0f);
		particles[i+NUM_PARTICLES/2].countdown = thd->jiffies() + (i+NUM_PARTICLES/2) * 5;
		particles[i+NUM_PARTICLES/2].theta =
			(2*3.1415926f/(NUM_PARTICLES/2)) / 2
			+ i * (2*3.1415926f/(NUM_PARTICLES/2));
		particles[i+NUM_PARTICLES/2].vtheta = 3*2*3.1415926f/8.0f;
	}

	return 0;
}

void particle_shutdown() { }

static void draw_part(float x, float y, float z, float scale, float a, float r, float g, float b) {
	vertex_ot_t v;
	float x1, y1, x2, y2, w, h;

	w = 32.0f * scale;
	h = 32.0f * scale;

	x1 = x + (32.0f - w)/2.0f;
	y1 = y + (32.0f - h)/2.0f;
	x2 = x1 + w;
	y2 = y1 + h;

	v.flags = TA_VERTEX_NORMAL;
	v.x = x1;
	v.y = y2;
	v.z = z;
	v.u = 0.0f; v.v = 1.0f;
	v.a = a; v.r = r; v.g = g; v.b = b;
	v.oa = v.or = v.og = v.ob = 0.0f;
	ta->commit_vertex(&v, sizeof(v));

	v.y = y1;
	v.v = 0.0f;
	ta->commit_vertex(&v, sizeof(v));

	v.x = x2;
	v.y = y2;
	v.u = v.v = 1.0f;
	ta->commit_vertex(&v, sizeof(v));

	v.flags = TA_VERTEX_EOL;
	v.y = y1;
	v.v = 0.0f;
	ta->commit_vertex(&v, sizeof(v));
}

void particle_shift(particle_t *part, float x, float y, float z) {
	int i;

	part->x = x;
	part->y = y;
	part->z = z;

	for (i=NUM_PARTS-1; i>0; i--) {
		part->parts[i].x = part->parts[i-1].x;
		part->parts[i].y = part->parts[i-1].y;
		part->parts[i].z = part->parts[i-1].z;
		part->parts[i].alpha = part->parts[i-1].alpha;
	}

	part->parts[0].x = part->x;
	part->parts[0].y = part->y;
	part->parts[0].z = part->z;

	for (i=0; i<NUM_PARTS; i++)
		part->parts[i].inten = (randnum(32) + (255 - 32)) / 256.0f;
}

void particle_draw_one(particle_t *part) {
	int i;
	float scale;
	poly_hdr_t poly;

	ta->poly_hdr_txr(&poly, TA_TRANSLUCENT, TA_ARGB4444_TWID,
		128, 128, txr_flame, TA_BILINEAR_FILTER);
	ta->commit_poly_hdr(&poly);

	for (i=0; i<NUM_PARTS; i++) {
		scale = 1.0f - (i / (NUM_PARTS + 2.0f));
		draw_part(part->parts[i].x, part->parts[i].y, part->parts[i].z, 
			scale * 0.6f,
			scale * 0.8f, 
			part->r * part->parts[i].inten,
			part->g * part->parts[i].inten,
			part->b * part->parts[i].inten);
	}

	ta->poly_hdr_txr(&poly, TA_TRANSLUCENT, TA_ARGB4444_TWID,
		128, 128, txr_flame_flare, TA_BILINEAR_FILTER);
	ta->commit_poly_hdr(&poly);

	/* for (i=0; i<NUM_PARTS; i++) {
		scale = 1.0f - (i / (NUM_PARTS / 2.0f));
		if (scale <= 0.0f) break;
		draw_part(part->parts[i].x, part->parts[i].y, 1.1f,
			part->parts[i].inten * 0.4f * scale,
			part->parts[i].inten * 0.8f * scale, 1.0f, 1.0f, 1.0f);
	} */
	draw_part(part->parts[0].x, part->parts[0].y, part->parts[0].z + 0.1f,
		0.4f, part->parts[0].inten,
		1.0f - part->r * 0.1f,
		1.0f - part->g * 0.1f,
		1.0f - part->b * 0.1f);
}

void particle_frame() {
	int i, jif;
	float vx, vy;

	jif = thd->jiffies();
	for (i=0; i<NUM_PARTICLES; i++) {
		/* if (particles[i].countdown == 0) {
			particle_shift(&particles[i], particles[i].vx, particles[i].vy);
			particles[i].vy += 0.1f/2;

			if (particles[i].x < 0.0f || particles[i].x > 640.0f
					|| particles[i].y > 490.0f) {
				particle_init_one(&particles[i], 320.0f, 480.0f, 512.0f);
				particles[i].vy = -4.0f/2;
				particles[i].vx = randnum(256) / 256.0f - 0.5f;
			}
		} else if (jif >= particles[i].countdown) {
			particles[i].countdown = 0;
			particles[i].vy = -4.0f/2;
			particles[i].vx = randnum(256) / 256.0f - 0.5f;
		} */

		particles[i].theta += 2*3.1415 / (60*4);
		// 150.0f
		vx = 170.0f * cos(particles[i].vtheta);
		vy = 170.0f * sin(particles[i].vtheta);
		particle_shift(&particles[i], 
			320.0f + vx*sin(particles[i].theta),
			240.0f + vy*sin(particles[i].theta),
			513.0f + 1.0f*cos(particles[i].theta));
		particles[i].vtheta += 2*3.1415 / (60*8);
	}

	for (i=0; i<NUM_PARTICLES; i++)
		particle_draw_one(&particles[i]);
}

