/*****************************************************************************
 * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Big particle-system.
 *//*
 * LEGAL:   COPYRIGHT (C) 2008 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#ifndef FX_PARTSYS_BIG_HH
#define FX_PARTSYS_BIG_HH 1

#include <list>
#include "fx/sprite.hh"
#include "fx/partsys.hh"

namespace fx {

class BigParticleSystem;

////////////////////////////////////////////////////////////////////////////////
/// @brief Big particle.
///
/// BigParticle contains a Sprite.
/// BigParticleSystem pulses BigParticles but doesn't animate them directly.
/// BigParticle::Tick() is meant to define a particle's animation.
///
class BigParticle : public Sprite
{
PREVENT_COPYING(BigParticle)
friend class BigParticleSystem;
public:
                    BigParticle( const Sprite::Args& spriteArgs,
                                 const Milliseconds lifetime );
    virtual         ~BigParticle();
    virtual void    Tick( const Milliseconds millisecElapsed ) = 0;
    void            SelfDestruct( void );
    Milliseconds    GetAge( const Milliseconds millisecElapsed,
                            const Milliseconds particleLifetime,
                            const Milliseconds timeOfDeath ) const
    {
        const Milliseconds beginning = timeOfDeath - particleLifetime;
        return millisecElapsed - beginning;  // age
    }

protected:
    Milliseconds    mTimeOfDeath;   ///< when to destroy the particle
public:
    DECLARE_TYPESIG(TYPESIG_BIG_PARTICLE)
};

////////////////////////////////////////////////////////////////////////////////
/// @brief Big particle-system.
///
/// Features of BigParticleSystem:
/// - can be derived and Tick() extended
/// - is created/contained by FX container
/// - every particle is pulsed by timer-tick (per-particle animation)
/// - adds particles
/// - ages particles
/// - deletes particles past their lifetime
///
/// To create a new particle system (to be coded in FX container):
/// - Make a derivative of BigParticleSystem that redefines Tick()
///   to add more particles every tick.
/// - Make a derivative of BigParticle which is passed to
///   DerivedParticleSystem::AttachParticle().
///
class BigParticleSystem : public ParticleSystem
{
PREVENT_COPYING(BigParticleSystem)
typedef ParticleSystem Parent;
friend class FX; friend class shptr<BigParticleSystem>;
protected:
    typedef std::list<shptr<BigParticle> > BigParticles;  ///< must be a list because of how expired Particles are removed

public:
    struct Args : public ParticleSystem::Args  // extend members
    {
        Args( const Milliseconds lifetime,
              const bool timerEnabled,
              const NodeSort& nodeSort );

        const NodeSort  mNodeSort;
    };

protected:
                        BigParticleSystem( const Args& args );
    virtual             ~BigParticleSystem();

protected:
    virtual void        Tick( const Milliseconds millisecElapsed );
    uint                GetParticleCount( void ) { return mBigParticles.size(); }
    void                AttachParticle( shptr<BigParticle> bigParticle );
    void                DetachOldestParticles( const uint count );
    NodeSort&           GetNodeSort( void ) { CHECK_TYPESIG(&mNodeSort,TYPESIG_NODE_SORT);
                                              return mNodeSort; }
private:
    void                DetachParticle( BigParticles::iterator iter );

protected:
    BigParticles        mBigParticles;      ///< container of BigParticle Objects
    NodeSort            mNodeSort;
    RefPtr<GroupNode>   mGroupNode;         ///< contains particles and their stateset
public:
    DECLARE_TYPESIG(TYPESIG_BIG_PARTICLE_SYSTEM)
};

} // namespace fx

#endif // FX_PARTSYS_BIG_HH
