/*
	Trig Wars.
	Copyright (c) 2008, Darragh Coy.
	All rights reserved.
	Original work(s), source code & author(s) details available at: http://www.darraghcoy.com

	Redistribution and use in source and binary forms, with or without modification, are permitted 
	provided that the following conditions are met:

		* 	Redistributions of source code must retain the above copyright notice, this list of 
			conditions and the following disclaimer.
		* 	Redistributions in binary form must reproduce the above copyright notice, this list of 
			conditions and the following disclaimer in the documentation.
		* 	Neither the name of the author nor the names of contributors may be used to endorse or 
			promote products derived from this software without specific prior written permission.
		* 	The use of any third party libraries, modules or data files provided with the source 
			form of the program must follow and respect the individual licensing terms of these 
			components. You do not have permission to modify or circumvent the licensing terms for 
			provided third party components unless the third party licenses specifically allow this. 
			If you do not agree to the terms of provided third party components then you do not have 
			permission to use them in your derived work(s).
		* 	The terms of this license do not apply to separate (but related) distributions if supplied 
			by the author(s), only to the contents of this source distribution, derived works, and the 
			binaries produced by either modified or unmodified versions of the source code. The terms 
			of this license do not also apply to any third party libraries or components provided with 
			the source distribution. Such third party elements are licensed under their own separate 
			agreements.

	THIS SOFTWARE IS PROVIDED BY DARRAGH COY ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
	BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
	ARE DISCLAIMED. IN NO EVENT SHALL DARRAGH COY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
	OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
	OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
	IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef PARTICLE_EMITTER_H
#define PARTICLE_EMITTER_H

//=====================================================================================================================
//=====================================================================================================================

#include "Graphics\VertexFormat.h"
#include "Graphics\PixelShader.h"
#include "Graphics\VertexShader.h"
#include "Graphics\ParticleEmitterBurst.h"

//=====================================================================================================================
//=====================================================================================================================

namespace Game
{
	//=================================================================================================================
	//=================================================================================================================
	
	class Display;
	class VertexBuffer;
	class VertexShaderManager;
	class PixelShaderManager;
	class VertexShader;
	class PixelShader;

	//=================================================================================================================
    /// @brief		This class allows bursts of particles to be generated. Handles the creation and drawing of the 
    ///				particles.
	//=================================================================================================================

    class ParticleEmitter : public ObjectBase
    {
		public:

			//=========================================================================================================
			// Functions
			//=========================================================================================================

				/// Creates the particle emitter.

				ParticleEmitter( Display * display , VertexShaderManager * vsh_mgr , PixelShaderManager * psh_mgr );
				
				/// Destroys the particle emitter
				
				virtual ~ParticleEmitter();
				
				/// Tells the object to announce it's type name: this is the type name without the Game:: namespace

				virtual const char * GetTypeName() const;						

				/// Updates all the particle bursts and advances their timing.

				void Update( float time_delta );				

				/// Draws all of the particles in the emitter

				void Draw( const Matrix4f & transform , const Vec2f & camera_pos );		

				/// Creates a directed burst of particles from the emitter.

				void CreateDirectedBurst
				(
					int					num_particles   ,
					const Texture &		texture			,
					const Vec2f &		position        ,
					const Vec2f &		direction       ,
					float				spread          ,
					float				live_time1      ,
					float				live_time2      ,
					float				size1           ,
					float				size2           ,
					const Color &		color1          ,
					const Color &		color2          ,
					float				speed1          ,
					float				speed2          ,
					bool				alpha_blend 
				);     

				/// Creates a burst of particles from the emitter in all directions.
		        
				void CreateBurst
				(
					int					num_particles   ,
					const Texture &		texture         ,
					const Vec2f &		position        ,
					float				live_time1      ,
					float				live_time2      ,
					float				size1           ,
					float				size2           ,
					const Color &		color1          ,
					const Color &		color2          ,
					float				speed1          ,
					float				speed2          ,
					bool				alpha_blend 
				);
				
				/// Returns the number of active particle bursts
				
				inline unsigned GetActiveBurstCount(){ return m_burst_pool->GetUsedCount(); }
				
		private:
		
			//=========================================================================================================
			// Constants
			//=========================================================================================================

				//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
				/// Maximum number of particles that can be drawn in one go in a burst. Attempts to create bursts bigger
				/// than this will be rebuked and the number of particles will be kept to this limit.
				//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
				
				static const unsigned PARTICLE_BUFFER_SIZE;
				
				/// Number of particle bursts to preallocate in the pool
				
				static const unsigned BURST_POOL_SIZE;
				
			//=========================================================================================================
			// Functions
			//=========================================================================================================
			
				/// Copying is disallowed			
				
				ParticleEmitter( const ParticleEmitter & p );
				
				/// Copying is disallowed
				
				ParticleEmitter & operator = ( const ParticleEmitter & p );
				
				/// Allocates a particle burst from the pool or creates a new one if the pool is fully used
				
				ParticleEmitterBurst * AllocBurst();
				
				/// Fills if the vertex buffer with all the data needed to render particles if it is valid
				
				void FillVertexBuffer();

			//=========================================================================================================
			// Variables
			//=========================================================================================================
			
				/// The display used by the particle emitter
				
				Display * m_display;

				/// Vertex buffer containing all of the vertices for the particles

				VertexBuffer * m_vertex_buffer;

				/// A pool containing all of the currently active particle bursts, as well as any spare ones

				Pool<ParticleEmitterBurst> * m_burst_pool;
				
				/// Vertex format to use for particles
				
				VertexFormat m_vf;
				
				/// Vertex shader to use for particles
				
				VertexShader m_vs;
	            
				/// Pixel shader to use for particles

				PixelShader m_ps;
				
				/// True if all our vertex and pixel shaders etc. are valid
				
				bool m_is_valid;
				
				/// A linked list holding all of the particle bursts that we pre-allocated
				
				std::list<ParticleEmitterBurst*> m_burst_allocs;
				
				/// Vertex shader uniform holding the two particle sizes in x and y and the two particle live times in z and w
				
				ShaderUniform m_u_sizes_and_live_times;
				
				/// Vertex shader uniform holding the particle angles in x and y and the particle speeds in z and w
				
				ShaderUniform m_u_angles_and_speeds;
				
				/// Vertex shader uniform holding the 1st particle color
				
				ShaderUniform m_u_color1;
				
				/// Vertex shader uniform holding the 2nd particle color
				
				ShaderUniform m_u_color2;
				
				/// Vertex shader uniform holding the random seed in x, and current time alive in y
				
				ShaderUniform m_u_random_seed_and_time_alive;
				
				/// Vertex shader uniform holding the transform matrix
				
				ShaderUniform m_u_transform;
    };
}

#endif
