#ifndef EXPLOSIONPARTICLESYSTEM
#define EXPLOSIONPARTICLESYSTEM
#include "particlesystem.h"
#include "util_vector.h"
#include "velocityparticle.h"
#include "cl_util.h"
#include "const.h"
#include "pm_shared.h"
#include "pmtrace.h"
#include "pm_defs.h"
#include "event_api.h"

#define NUMBER_OF_SMOKETRAILS 7
#define ENG_PM_POINT_CONTENTS gEngfuncs.PM_PointContents

class SmokeTrail
{
public:	
	vec3_t startorigin;
	vec3_t origin;
	vec3_t velocity;
	vec3_t acceleration;
	float size;
	int particles;
	int stop;
};

template <class TParticle> class TExplosionParticleSystem:public TParticleSystem<TParticle>
{
public:	
	TExplosionParticleSystem(int ent, int type, vec3_t origin, int radius, HSPRITE sprite):TParticleSystem<TParticle>(ent,type)
	{	m_fRemove = false;
		m_hsprDust = sprite;
		m_flStartTime = gEngfuncs.GetClientTime();
		m_iMaxParticles = radius;
		/*
		for (int i=0;i<NUMBER_OF_DUSTPARTICLES;i++)
		{	
			vec3_t vecOrigin = origin;
			vecOrigin.z += gEngfuncs.pfnRandomFloat( 0, 10 );
			vec3_t vecVelocity;
			vecVelocity.x = gEngfuncs.pfnRandomFloat( -1, 1 );
			vecVelocity.y = gEngfuncs.pfnRandomFloat( -1, 1 );
			vecVelocity.z = gEngfuncs.pfnRandomFloat( -1, 1 );
			vecVelocity = vecVelocity.Normalize()*gEngfuncs.pfnRandomFloat( 300, 400 );
			vec3_t vecAcceleration = Vector(0.0,0.0,-6.0);
			
			TParticle p = TParticle(vecOrigin,vecVelocity,vecAcceleration,sprite);
			p.m_flSize = gEngfuncs.pfnRandomFloat( 1, 10 );
			particles.push_back(p);
		}
		*/
		for (int i=0;i<NUMBER_OF_SMOKETRAILS;i++)
		{	
			vec3_t vecOrigin = origin;
			//vecOrigin.x += gEngfuncs.pfnRandomFloat( -0.25*radius, 0.25*radius );
			//vecOrigin.y += gEngfuncs.pfnRandomFloat( -0.25*radius, 0.25*radius );
			vec3_t vecVelocity;
			vecVelocity.x = gEngfuncs.pfnRandomFloat( -1, 1 );
			vecVelocity.y = gEngfuncs.pfnRandomFloat( -1, 1 );
			vecVelocity.z = gEngfuncs.pfnRandomFloat( -1, 1 );
			
			smokeTrails[i].origin = vecOrigin;
			smokeTrails[i].startorigin = vecOrigin;
			smokeTrails[i].velocity = vecVelocity.Normalize()*gEngfuncs.pfnRandomFloat( 200, 100 ) * radius / 100;
			smokeTrails[i].acceleration = Vector(0.0,0.0,-150.0);
			smokeTrails[i].size = gEngfuncs.pfnRandomFloat( 50, 60 ) * radius / 100;
			smokeTrails[i].particles = 0;
			smokeTrails[i].stop = false;
		
			Particle p = Particle(vecOrigin,m_hsprDust);
			p.m_flSize = smokeTrails[i].size;
			p.m_flMaxLifeTime = m_flStartTime + 3.0;
			particles.push_back(p);			
		}
	}

	/**
	 * Updates the physics for all particles in the system
	 * @param timeDiff time difference since last draw
	 */	 	
	virtual void think(float time)
	{
		float flTime = time-m_flStartTime;
		for (int i=0;i<NUMBER_OF_SMOKETRAILS;i++)
		{	if (!smokeTrails[i].stop)
		
			{
				vec3_t vecOrigin = smokeTrails[i].startorigin + smokeTrails[i].velocity * flTime + 0.5 * smokeTrails[i].acceleration * flTime * flTime;
				if ((vecOrigin - smokeTrails[i].origin).Length()>smokeTrails[i].size*0.15 && smokeTrails[i].particles<m_iMaxParticles)
				{	if (ENG_PM_POINT_CONTENTS(vecOrigin,NULL)==CONTENT_EMPTY)
					{	Particle p = Particle(vecOrigin,m_hsprDust);
						smokeTrails[i].size*=0.85;
						smokeTrails[i].particles++;
						p.m_flSize = smokeTrails[i].size;
						p.m_flMaxLifeTime = time + 3.0;
						particles.push_back(p);
						smokeTrails[i].origin = vecOrigin;
					}
					else
					{	smokeTrails[i].stop = true;
					}
				}
			}
		}
		vector<TParticle>::iterator b = particles.begin();
 		while (b != particles.end())
 		{
  			if (b->m_flMaxLifeTime>time)
			{	b->doThink(time);
				float flRelLife = (b->m_flMaxLifeTime-time)/(b->m_flMaxLifeTime-b->m_flStartTime);
				b->color.x = b->color.y = b->color.z = flRelLife;				
   				b++;
			}
			else
			{	b=particles.erase(b);
			}
   		}

		//remove if no more particles to draw
		if(particles.size()==0)
		{	m_fRemove = true;
		}
 	}
private:	
	SmokeTrail smokeTrails[NUMBER_OF_SMOKETRAILS];
	HSPRITE m_hsprDust;
	float m_flStartTime;
	int m_iMaxParticles;
};
#endif