#include "../include/zf.h"

/* #include <GL/glut.h> */

#define EXPLOSION0 "../data/sound_effects/knokart.mp3"
#define EXPLOSION1 "../data/sound_effects/waterxplo.mp3"
#define EXPLOSION2 "../data/sound_effects/explosion.mp3"
#define NUM_EXPLOSIONS 2

typedef struct Explosion Explosion;

struct Explosion
{
    unsigned int ref_count;

    CLvertex position;    
    CLnormal velocity;
    
    float max_size;
    float size;
};

static ZfSmartPointer smart_pointer; /* interface for leeches */

static ZfAudioSample* explosion0;
static ZfAudioSample* explosion1;
static ZfAudioSample* explosion2;

static bool
is_valid(Explosion* explosion)
{
    return explosion->size < explosion->max_size;
}

static void
reference(Explosion* explosion)
{
    explosion->ref_count++;
}

static void
release(Explosion* explosion)
{
    explosion->ref_count--;

    if (explosion->ref_count == 0)
	g_free(explosion);
}

static void
animate(Explosion* explosion)
{
    explosion->size += 0.1f;
}

static void
render(Explosion* explosion)
{
    float t;

    glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT);

    glDisable(GL_LIGHTING);
    glDisable(GL_TEXTURE_2D);
    /* glEnable(GL_CULL_FACE); */

    t = 1.0f - (float)explosion->size/(float)explosion->max_size;

    glColor4f(0.8f + 0.2f * t, 
	      0.5f + 0.3f * t,
	      0.2f,
	      t);  /*   1.0f - explosion->size/explosion->max_size);*/

    glPushMatrix();
    glTranslatef(explosion->position.x,
		 explosion->position.y,
		 explosion->position.z);

    glutSolidSphere(explosion->size, 8, 8);

    glPopMatrix();

    glPopAttrib();
}

void
zf_explosion_init(void)
{
    smart_pointer.is_valid = (ZfIsValid*) is_valid;
    smart_pointer.reference = (ZfReference*) reference;
    smart_pointer.release = (ZfRelease*) release;

    /* load some explosion sounds */
    explosion0 = zf_audio_sample_load(EXPLOSION0);
    explosion1 = zf_audio_sample_load(EXPLOSION1);
    explosion2 = zf_audio_sample_load(EXPLOSION2);
    zf_audio_sample_set_volume(explosion0, 128);
    zf_audio_sample_set_volume(explosion1, 128);
    zf_audio_sample_set_volume(explosion2, 128);
}

void
zf_explosion_close(void)
{
    /* nothing atm - texture later? */
    zf_audio_sample_destroy(explosion0);
    zf_audio_sample_destroy(explosion1);
    zf_audio_sample_destroy(explosion2);
}

void
zf_explosion_new(const CLvertex* position,
		 float size)
{
    /* play sound */
    switch (rand() % NUM_EXPLOSIONS)
    {
    case 0:
	//printf("%s() : play explosion 0\n", __FUNCTION__);
	zf_audio_sample_play(explosion0);
    case 1:
	//printf("%s() : play explosion 1\n", __FUNCTION__);
	zf_audio_sample_play(explosion1);
#if 0
    case 2:
	printf("%s() : play explosion 2\n", __FUNCTION__);
	zf_audio_sample_play(explosion2);
#endif

    default:
	//printf("%s() : no explosion sound\n", __FUNCTION__);
	break;
    }

    /* major explosion */
    {
	Explosion* explosion;
	
	explosion = g_new(Explosion, 1);
	
	clCopyVertex(&explosion->position, position);
	
	explosion->ref_count = 0;
	
	explosion->size = 0.0f;
	explosion->max_size = size;
	
	zf_animation_system_add(explosion,
				&smart_pointer,
				(ZfAnimate*) animate);
	
	zf_render_system_add_translucent(explosion,
					 &smart_pointer,
					 (ZfRender*)render);
    }

#if 1
    /* mini explosions */
    {
	unsigned int i;
	unsigned int num_mini_explosions = 10;

	for (i = 0 ; i < num_mini_explosions ; i++)
	{
	    Explosion* explosion;
	    
	    explosion = g_new(Explosion, 1);
	    
	    /*	    clCopyVertex(&explosion->position, position);*/
	    cluSetVertex(&explosion->position,
			 position->x + ((float)rand() / RAND_MAX - 0.5f),
			 position->y + ((float)rand() / RAND_MAX - 0.5f),
			 position->z + ((float)rand() / RAND_MAX - 0.5f));
	    
	    explosion->ref_count = 0;
	    
	    explosion->size = 0.0f;
	    explosion->max_size = (float)rand() / RAND_MAX * 2.0f;
	    
	    zf_animation_system_add(explosion,
				    &smart_pointer,
				    (ZfAnimate*) animate);
	    
	    zf_render_system_add_translucent(explosion,
					     &smart_pointer,
					     (ZfRender*)render);
	}
    }

    /* smoke particles */
    while (((float)rand() / RAND_MAX < 0.9f))
    {
	CLvertex pos;
	CLnormal velocity = {(float)rand() / RAND_MAX - 0.5f,
			     5.0f,
			     (float)rand() / RAND_MAX - 0.5f};

	CLcolour colour = {0.8f, 0.8f, 0.8f, 0.8f};
	
	cluNormalNormalise(&velocity);
	cluNormalScale(&velocity, 0.025f);

	cluSetVertex(&pos,
		     position->x + ((float)rand() / RAND_MAX - 0.5f),
		     position->y + ((float)rand() / RAND_MAX - 0.5f),
		     position->z + ((float)rand() / RAND_MAX - 0.5f));

	zf_particle_system_add_particle(&pos,
					&velocity,
					0.02f,
					&colour,
					140,
					8.0f);
    }

    /* fire particles */
    {
	unsigned int i;
	unsigned int num_fire_particles = 100;
	
	for (i = 0 ; i < num_fire_particles ; i++)
	{
	    CLvertex pos;
	    CLnormal velocity = {(float)rand() / RAND_MAX - 0.5f,
				 (float)rand() / RAND_MAX - 0.5f,
				 (float)rand() / RAND_MAX - 0.5f};
	    
	    CLcolour colour = {1.0f,
			       (float)rand() / RAND_MAX - 0.5f,
			       0.0f,
			       0.8f};
	    
	    cluNormalNormalise(&velocity);
	    cluNormalScale(&velocity, 0.1f);

	    cluSetVertex(&pos,
			 position->x + ((float)rand() / RAND_MAX - 0.5f),
			 position->y + ((float)rand() / RAND_MAX - 0.5f),
			 position->z + ((float)rand() / RAND_MAX - 0.5f));
	    
	    zf_particle_system_add_particle(&pos,
					    &velocity,
					    0.2f,
					    &colour,
					    (float)rand() / RAND_MAX * 100,
					    (float)rand() / RAND_MAX * 16.0f);
	}
    }

#endif
}
