#ifndef _GRAPRA_PARTICLESYSTEM_
#define _GRAPRA_PARTICLESYSTEM_

#include "Vector3d.hpp"
#include <deque>
#include <boost/bind.hpp>
#include "gl.hpp"

struct s_Particle
{
	Vector3f Position;
	Vector3f Velocity;
	float Size;
	float Transparency;
	float Age;

	s_Particle(): Size(1), Transparency(1), Age(0) {}
};


class ParticleSystem
{
public:
	///VelGenFun is Vector3f Fun()
	ParticleSystem(Vector3f Origin, std::string Texture);

	///updates all particles
	void onTick(float Time);

	///draws all particles
	void onRender();

	bool IsDead() { return m_Particles.empty(); }
protected:
	virtual s_Particle GenerateParticle()=0;
	virtual void UpdateParticle(s_Particle& Pat, float Time)=0;

	Vector3f m_Color;
	float m_StartAlpha, m_EndAlpha;
	Vector3f m_Origin;///<the origins of all particles
	Vector3f m_Gravity;///<garvity which accelerates each particle
	float m_ParticleLifetime;
	std::deque<s_Particle> m_Particles;

	GLuint m_Texture;
};


//specific particle systems:

class SmokeParticle : public ParticleSystem
{
public:
	SmokeParticle(Vector3f Origin);
protected:
	s_Particle GenerateParticle() override;
	void UpdateParticle(s_Particle& Pat, float Time) override;
};


class SparksParticle : public ParticleSystem
{
public:
	SparksParticle(Vector3f Origin, Vector3f Color);
protected:
	s_Particle GenerateParticle() override;
	void UpdateParticle(s_Particle& Pat, float Time) override;
};


class FireParticle : public ParticleSystem
{
public:
	FireParticle(Vector3f Origin, Vector3f Color, float Size);
protected:
	s_Particle GenerateParticle() override;
	void UpdateParticle(s_Particle& Pat, float Time) override;
	float m_FireEndSize;
};

#endif