/*
	ZParticleEmitter.h
	Author: James Russell <jcrussell@762studios.com>

	Purpose: Particle emitter class, which maintains a set of strategies used to store, create, update, and render
			 particles.

	Changelog
	2011/08/28 - creation (jcrussell)
*/

#pragma once

#ifndef _ZPARTICLEEMITTER_H
#define _ZPARTICLEEMITTER_H

#include <ZRenderer/ZRenderer.hpp>
#include <ZRendererUtil/ZParticleStorageAllocator.h>
#include <ZRendererUtil/ZParticleSpawnStrategy.h>
#include <ZRendererUtil/ZParticleUpdateStrategy.h>
#include <ZRendererUtil/ZParticleRenderStrategy.h>

//Forward Declaration
class ZParticleEffect;

class ZParticleEmitter
{
protected:
	//Number of particles at a time this emitter supports
	size_t MaxParticles;

	//Boolean indicating this emitter is complete (no longer emits particles)
	bool bIsFinished;

	//The transform for the particle emitter
	ZMatrix44f Transform;

	//Particle Generator
	ZPtr<ZParticleStorageAllocator> StorageAllocator;

	//Particle Spawn Strategy
	ZPtr<ZParticleSpawnStrategy> SpawnStrategy;

	//Particle Update Strategy
	ZPtr<ZParticleUpdateStrategy> UpdateStrategy;

	//Particle Render Strategy
	ZPtr<ZParticleRenderStrategy> RenderStrategy;

public:
	/*
	Default Constructor.
	*/
	ZParticleEmitter();

	/*
	Destructor.
	*/
	~ZParticleEmitter();

	/*
	public ZParticleEmitter::GetMaxParticles
	
	Returns the current amount of max particles this particle emitter supports.

	@return (size_t)
	@context (all)
	*/
	size_t GetMaxParticles();

	/*
	public ZParticleEmitter::GetTransform
	
	Gets the local transform for this particle emitter.
	
	@return (ZMatrix44f) - local transform for this emitter
	@context (all)
	*/
	ZMatrix44f GetTransform();

	/*
	public ZParticleEmitter::IsFinished

	Returns true if this particle emitter will no longer emit particles.

	@return (bool) - true if finished, false otherwise
	@context (all)
	*/
	bool IsFinished();

	/*
	public ZParticleEmitter::Render
	
	Renders the contained particles using the provided render strategy.
	
	@param _particleEffect - the parent particle effect
	@param _renderer - the renderer to use
	@param _context - frame context to render with
	@param _drawGroup - the draw group to render with
	@return (void)
	@context (all)
	*/
	void Render(ZParticleEffect* _particleEffect, ZRenderer* _renderer, ZFrameContext _context, int _drawGroup);

	/*
	public ZParticleEmitter::SetMaxParticles
	
	Sets the maximum number of particles this emitter supports.
	
	@param _maxParticles - the maximum particle count
	@return (void)
	@context (all)
	*/
	void SetMaxParticles(size_t _maxParticles);

	/*
	public ZParticleEmitter::SetFinished
	
	Sets completion status of this emitter to the provided value.
	
	@param _status - completion status (true if finished, false otherwise)
	@return (void)
	@context (all)
	*/
	void SetFinished(bool _status);

	/*
	public ZParticleEmitter::SetParticleStorageAllocator
	
	Sets the particle storage allocator for this particle emitter.  This will call
	ZParticleStorageAllocator::AllocateParticleStorage.
	
	@param _allocator - the allocator to use
	@param _maxParticles - the number of particles to allocate storage for
	@return (ZPtr<ZParticleStorageAllocator>) - the storage allocator that was previously attached
	@context (all)
	*/
	ZPtr<ZParticleStorageAllocator> SetParticleStorageAllocator(ZPtr<ZParticleStorageAllocator> _allocator, size_t _maxParticles);

	/*
	public ZParticleEmitter::SetParticleSpawnStrategy
	
	Sets the particle span strategy for this particle emitter.
	
	@param _spawnStrategy - the spawn strategy to use
	@return (ZPtr<ZParticleSpawnStrategy>) - the spawn strategy that was previously attached
	@context (all)
	*/
	ZPtr<ZParticleSpawnStrategy> SetParticleSpawnStrategy(ZPtr<ZParticleSpawnStrategy> _spawnStrategy);

	/*
	public ZParticleEmitter::SetParticleUpdateStrategy
	
	Sets the particle update strategy for this particle emitter.
	
	@param _updateStrategy - the particle update strategy to use
	@return (ZPtr<ZParticleUpdateStrategy>) - the update strategy that was previously attached
	@context (all)
	*/
	ZPtr<ZParticleUpdateStrategy> SetParticleUpdateStrategy(ZPtr<ZParticleUpdateStrategy> _updateStrategy);

	/*
	public ZParticleEmitter::SetParticleRenderStrategy
	
	Sets the render strategy for this particle emitter.  This will call AllocateBuffers on the render strategy.
	
	@param _renderStrategy - the render strategy to use
	@param _renderer - the renderer to allocate buffers from
	@return (ZPtr<ZParticleRenderStrategy>) - the render strategy that was previously attached
	@context (all)
	*/
	ZPtr<ZParticleRenderStrategy> SetParticleRenderStrategy(ZPtr<ZParticleRenderStrategy> _renderStrategy, ZRenderer *_renderer);

	/*
	public ZParticleEmitter::SetTransform
	
	Sets the transform for this particle emitter.
	
	@param _transform - the transform to use
	@return (void)
	@context (all)
	*/
	void SetTransform(ZMatrix44f _transform);

	/*
	public ZParticleEmitter::Update
	
	Runs through the various installed strategies, which can will both create new particles (as dictated by strategy)
	and update existing ones.
	
	@param _particleEffect - the parent particle effect
	@param _dt - the time (in milliseconds) since last update
	@return (void)
	@context (all)
	*/
	void Update(ZParticleEffect* _particleEffect, size_t _dt);
};

#endif
 
