#include "hud.h"
#include "parsemsg.h"
#include "const.h"
#include "cl_util.h"
#include "r_efx.h"
#include "event_api.h"
#include <math.h>
#include "vrml.h"
#include "../common/explosioncolors.h"

#define ENG_PM_POINT_CONTENTS gEngfuncs.PM_PointContents

DECLARE_MESSAGE(m_Explosion, Explosion);
explosion *tri_exp;
VRMLData gVRMLSphereHigh;
VRMLData gVRMLSphereLow;
VRMLData gVRMLDome;
	
int CHudExplosion::Init(void)
{	HOOK_MESSAGE(Explosion);
	tri_exp = NULL;
	m_flLastResize = 0;
	gHUD.AddHudElem(this);
	m_iFlags |= HUD_ACTIVE;
	return 1;
}

void CHudExplosion::Reset()
{	explosion *current = tri_exp;
	//remove all explosions
	while (current)
	{
		current = RemoveExplosion(current);
	}
	tri_exp = NULL;
	m_flLastResize = 0;
}

int CHudExplosion::VidInit(void)
{	ParseVRML("models/sphere.wrl", gVRMLSphereHigh);
	ParseVRML("models/spherelow.wrl", gVRMLSphereLow);
	ParseVRML("models/dome.wrl", gVRMLDome);
	m_hsprExplosionBlue = SPR_Load("sprites/blueexplosion.spr");
	m_hsprExplosionGreen = SPR_Load("sprites/greenexplosion.spr");
	m_hsprExplosionOrange = SPR_Load("sprites/orangeexplosion.spr");
	m_hsprExplosionPurple = SPR_Load("sprites/purpleexplosion.spr");
	m_hsprExplosionYellow = SPR_Load("sprites/yellowexplosion.spr");
	m_hsprExplosionRed = SPR_Load("sprites/redexplosion.spr");
	m_hsprExplosionWhite = SPR_Load("sprites/whiteexplosion.spr");
	m_hsprFlareSprite = SPR_Load("sprites/explosionflare.spr");
	m_hsprExplosionA = SPR_Load("sprites/explosionbluea.spr");
	m_hsprExplosionB = SPR_Load("sprites/explosionblueb.spr");
	m_hsprExplosionGlow = SPR_Load("sprites/explosionglow.spr");
	return 1;
}

// added by Pcjoe
void CHudExplosion::AnimateExplosion(explosion *pCurrent, float flTime)
{
	// Used to change frames for the Lighting
	if(pCurrent->m_flFrameTime < flTime)
	{	pCurrent->m_flFrameTime = flTime + 0.05;

		// Next Frame in the sprite
		if(pCurrent->m_iFrame < SPR_Frames(pCurrent->sprite)-1)
		{	pCurrent->m_iFrame++;	
		}
		// Reset the animation
		else
		{	pCurrent->m_iFrame = 0;
		}
	}
	
}

int CHudExplosion::Draw(float flTime)
{	
	// Set time difference
	SetTimeDifference( flTime );

	explosion *current = tri_exp;
	while (current)
	{	//current->light->radius = current->radius * 2;
		
		// Animate the explosion
		AnimateExplosion(current, flTime);

		// Increase/Decrease size
		if (current->expand)
		{	if(current->radius > current->maxradius)
			{	current->expand = false;
			}
			else
			{	current->radius += (400 + current->radius * 4) * m_flTimeDifference;
			}
			current = current->next;
		}
		else if (current->radius > 1)
		{	current->radius -= (365 + (current->maxradius - current->radius)) * m_flTimeDifference;
			current = current->next;				
		}
		else
		{	current = RemoveExplosion(current);
		}			
	}

	// Reset time difference
	ResetTimeDifference( flTime );
	return 1;
}

explosion* CHudExplosion::RemoveExplosion(explosion *exp)
{	explosion *prev;
	prev = tri_exp;
	
	//should never happen...
	if (!prev)
	{	return NULL;
	}
	
	//remove 1st explosion
	if (prev == exp)
	{	tri_exp = prev->next;
		delete exp;
		return tri_exp;
	}
	
	//find explosion
	while (prev->next != exp)
	{	prev = prev->next;
		//should not happen...
		if (!prev)
		{	return NULL;
		}
	}
	prev->next = exp->next;
	delete exp;
	return prev->next;
}

void CHudExplosion::AddExplosion(vec3_t org, int radius, HSPRITE sprite)
{	//create explosion
	explosion *new_exp = new explosion;
	new_exp->pos.x = org.x;
	new_exp->pos.y = org.y;
	new_exp->pos.z = org.z;

	new_exp->flare_sprite = m_hsprFlareSprite;
	new_exp->spritea = m_hsprExplosionA;
	new_exp->spriteb = m_hsprExplosionA;
	new_exp->spriteglow = m_hsprExplosionGlow;
	// edited/added by Pcjoe
	new_exp->maxradius = radius;
	new_exp->radius = 2;
	new_exp->expand = true;
	new_exp->m_iFrame = 0;
	new_exp->m_flFrameTime = 0;

	new_exp->sprite = sprite;
	
	new_exp->next = NULL;
			
	//first explosion
	if (!tri_exp)
	{	tri_exp = new_exp;		
	}
	else
	{	//add it as last explosion
		explosion *current = tri_exp;
		while(current->next)
		{	current = current->next;
		}
		current->next = new_exp;
	}	
}

int CHudExplosion::MsgFunc_Explosion(const char *pszName,  int iSize, void *pbuf )
{	BEGIN_READ( pbuf, iSize );
	vec3_t vecMiddle;
	vecMiddle.x = READ_COORD();
	vecMiddle.y = READ_COORD();
	vecMiddle.z = READ_COORD();

	int radius = READ_LONG();
	// added by Pcjoe
	// Quick check to make sure the radius isnt too small
	if (radius < 4)
	{	radius = 4;
	}

	int iExplosionColor = READ_BYTE();
	HSPRITE hsprExplosionSprite;
	switch (iExplosionColor)
	{
	case BLUE_EXPLOSION:
		hsprExplosionSprite = m_hsprExplosionBlue;
		break;
	case GREEN_EXPLOSION:
		hsprExplosionSprite = m_hsprExplosionGreen;
		break;		
	case ORANGE_EXPLOSION:
		hsprExplosionSprite = m_hsprExplosionOrange;
		break;
	case PURPLE_EXPLOSION:
		hsprExplosionSprite = m_hsprExplosionPurple;
		break;
	case YELLOW_EXPLOSION:
		hsprExplosionSprite = m_hsprExplosionYellow;
		break;
	case RED_EXPLOSION:
		hsprExplosionSprite = m_hsprExplosionRed;
		break;		
	case WHITE_EXPLOSION:
		hsprExplosionSprite = m_hsprExplosionWhite;
		break;	
	default:
		//invalid color, don't add this explosion
		return 1;
	};

	AddExplosion(vecMiddle, radius, hsprExplosionSprite);

	//play explosion sound
	gEngfuncs.pEventAPI->EV_PlaySound( -1, vecMiddle, 0, "weapons/explosion.wav", 1.0, ATTN_NORM, 0, PITCH_NORM );	
	return 1;
}
