/***************************************************************************
 * animation.h  -  header for the corresponding cpp file
 *
 * Copyright (C) 2003 - 2008 Florian Richter
 ***************************************************************************/
/*
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef SMC_ANIMATION_H
#define SMC_ANIMATION_H

#include "../objects/movingsprite.h"
#include "../objects/objectsprite.h"
#include "../core/obj_manager.h"

/* *** *** *** *** *** *** *** Animation definitions *** *** *** *** *** *** *** *** *** *** */

enum AnimationEffect
{
	ANIM_UNDEFINED,
	BLINKING_POINTS,
	FIRE_EXPLOSION,
	PARTICLE_EXPLOSION,
};

/* *** *** *** *** *** *** *** Particle blending definitions *** *** *** *** *** *** *** *** *** *** */

enum BlendingMode
{
	BLEND_NONE,
	BLEND_ADD,
	BLEND_DRIVE
	// todo : more
};

/* *** *** *** *** *** *** *** Base Animation class *** *** *** *** *** *** *** *** *** *** */

class cAnimation : public cImageObjectSprite
{
public:
	cAnimation( float x = 0, float y = 0 );
	virtual ~cAnimation( void );

	// initialize animation
	virtual void Init_Anim( void );
	// update animation
	virtual void Update( void );
	// draw animation
	virtual void Draw( cSurfaceRequest *request = NULL );

	// Set time to live for Objects in seconds
	void Set_Time_to_Live( float time, float time_rand = 0 );
	/* Set speed of fading out ( 0.01 - 100 )
	* the lower the longer it takes
	* Note : only useful for non particle animation Objects
	*/
	void Set_Fading_Speed( float speed );
	// set z position
	virtual void Set_Pos_Z( float pos, float pos_rand = 0 );

	// Z random position
	float posz_rand;
	// fading out speed
	float fading_speed;
	// object time to live
	float time_to_live, time_to_live_rand;
	// animation type
	AnimationEffect animtype;
};

/* *** *** *** *** *** *** *** *** Blinking points *** *** *** *** *** *** *** *** *** */

class cAnimation_Goldpiece : public cAnimation
{
public:
	cAnimation_Goldpiece( float posx, float posy, float height = 40, float width = 20 );
	virtual ~cAnimation_Goldpiece( void );

	// update
	virtual void Update( void );
	// draw
	virtual void Draw( cSurfaceRequest *request = NULL );

	typedef vector<cSprite *> BlinkPointList;
	BlinkPointList objects;
	
};

/* *** *** *** *** *** *** *** Fireball Animation *** *** *** *** *** *** *** *** *** *** */

class cAnimation_Fireball_Item : public cImageObjectSprite
{
public:
	cAnimation_Fireball_Item( void )
	: cImageObjectSprite()
	{
		counter = 0;
	}

	virtual ~cAnimation_Fireball_Item( void ) {}

	// lifetime
	float counter;
};

class cAnimation_Fireball : public cAnimation
{
public:
	cAnimation_Fireball( float posx, float posy, unsigned int power = 5 );
	virtual ~cAnimation_Fireball( void );

	// initialize animation
	virtual void Init_Anim( void );
	// update
	virtual void Update( void );
	// draw
	virtual void Draw( cSurfaceRequest *request = NULL );

	typedef vector<cAnimation_Fireball_Item *> FireAnimList;
	FireAnimList objects;
};

/* *** *** *** *** *** *** *** Particle Emitter *** *** *** *** *** *** *** *** *** *** */

class cParticle_Emitter;

// Particle Item
class cParticle : public cMovingSprite
{
public:
	cParticle( void );
	virtual ~cParticle( void );

	// update
	virtual void Update( void );
	// draw
	virtual void Draw( cParticle_Emitter *origin );

	// set gravity
	void Set_Gravity( float x, float y );

	// time to live
	float time_to_live;
	// constant rotation
	float const_rotx, const_roty, const_rotz;
	// particle gravity
	float gravity_x, gravity_y;

	// fading position value
	float fade_pos;
};

// Particle Emitter
class cParticle_Emitter : public cAnimation
{
public:
	// constructor
	cParticle_Emitter( void );
	// create from stream
	cParticle_Emitter( CEGUI::XMLAttributes &attributes );
	// destructor
	virtual ~cParticle_Emitter( void );

	// create from stream
	virtual void Create_from_Stream( CEGUI::XMLAttributes &attributes );
	// save to stream
	virtual void Save_to_Stream( ofstream &file );

	// Init
	virtual void Init( void );
	// copy
	virtual cParticle_Emitter *Copy( void );
	// initialize animation
	virtual void Init_Anim( void );
	// Emit Particles
	virtual void Emit( void );
	// Clear Particles and Animation data
	virtual void Clear( void );

	// Update given settings
	virtual void Update( void );
	// Draw everything
	virtual void Draw( cSurfaceRequest *request = NULL );

	// if update is valid for the current state
	virtual bool Is_Update_Valid( void );
	// if draw is valid for the current state and position
	virtual bool Is_Draw_Valid( void );

	// Set the Emitter rect
	void Set_Emitter_Rect( float x, float y, float w = 0, float h = 0 );
	void Set_Emitter_Rect( GL_rect r );
	/* Set time to live for the Emitter in seconds
	 * set -1 for infinite
	*/
	void Set_Emitter_Time_to_Live( float time );
	// Set time between Iterations
	void Set_Emitter_Iteration_Interval( float time );
	// Set Particle Count/Quota
	void Set_Quota( unsigned int size );
	// Set speed ( 0 - 100 )
	void Set_Speed( float vel_base, float vel_random = 2 );
	// Set start rotation z uses start direction
	void Set_Start_Rot_Z_Uses_Direction( bool enable );
	// Set x constant rotation
	void Set_Const_Rotation_X( float rot, float rot_random = 0 );
	// Set y constant rotation
	void Set_Const_Rotation_Y( float rot, float rot_random = 0 );
	// Set z constant rotation
	void Set_Const_Rotation_Z( float rot, float rot_random = 0 );
	/* Set direction range ( 0 - 360 )
	 * 0 : Right, 90 Down, 180 Left, 270 Up
	*/
	void Set_Direction_Range( float start, float range = 0 );
	// Set image scale ( 0.01 - 100 )
	virtual void Set_Scale( float nscale, float scale_random = 0 );
	// Set horizontal gravity
	void Set_Horizontal_Gravity( float start, float random = 0 );
	// Set vertical gravity
	void Set_Vertical_Gravity( float start, float random = 0 );
	// Set the Color
	virtual void Set_Color( Color col, Color col_rand = Color( static_cast<Uint8>(0) ) );
	// Set fading type
	void Set_Fading_Size( bool enable );
	void Set_Fading_Alpha( bool enable );
	void Set_Fading_Color( bool enable );
	// Set blending mode
	virtual void Set_Blending( BlendingMode mode );
	// Set image
	virtual void Set_Image( cGL_Surface *img );
	// Set the file name
	virtual void Set_Filename( string str_filename );

	// editor activation
	virtual void Editor_Activate( void );
	// position z base key up event
	bool Editor_Pos_Z_Base_Key( const CEGUI::EventArgs &event );
	// position z rand key up event
	bool Editor_Pos_Z_Rand_Key( const CEGUI::EventArgs &event );
	// editor filename key up event
	bool Editor_Filename_Key( const CEGUI::EventArgs &event );
	// emitter width key up event
	bool Editor_Emitter_Width_Key( const CEGUI::EventArgs &event );
	// emitter height key up event
	bool Editor_Emitter_Height_Key( const CEGUI::EventArgs &event );
	// emitter time to live key up event
	bool Editor_Emitter_Time_To_Live_Key( const CEGUI::EventArgs &event );
	// emitter interval key up event
	bool Editor_Emitter_Interval_Key( const CEGUI::EventArgs &event );
	// quota key up event
	bool Editor_Quota_Key( const CEGUI::EventArgs &event );
	// ttl base key up event
	bool Editor_Ttl_Base_Key( const CEGUI::EventArgs &event );
	// ttl rand key up event
	bool Editor_Ttl_Rand_Key( const CEGUI::EventArgs &event );
	// velocity base key up event
	bool Editor_Velocity_Base_Key( const CEGUI::EventArgs &event );
	// velocity rand key up event
	bool Editor_Velocity_Rand_Key( const CEGUI::EventArgs &event );
	// start rotation x base key up event
	bool Editor_Rotation_X_Base_Key( const CEGUI::EventArgs &event );
	// start rotation y base key up event
	bool Editor_Rotation_Y_Base_Key( const CEGUI::EventArgs &event );
	// start rotation z base key up event
	bool Editor_Rotation_Z_Base_Key( const CEGUI::EventArgs &event );
	// start rotation z uses start direction event
	bool Editor_Start_Rot_Z_Uses_Direction_Changed( const CEGUI::EventArgs &event );
	// constant rotation x base key up event
	bool Editor_Const_Rotation_X_Base_Key( const CEGUI::EventArgs &event );
	// constant rotation x rand key up event
	bool Editor_Const_Rotation_X_Rand_Key( const CEGUI::EventArgs &event );
	// constant rotation y base key up event
	bool Editor_Const_Rotation_Y_Base_Key( const CEGUI::EventArgs &event );
	// constant rotation y rand key up event
	bool Editor_Const_Rotation_Y_Rand_Key( const CEGUI::EventArgs &event );
	// constant rotation z base key up event
	bool Editor_Const_Rotation_Z_Base_Key( const CEGUI::EventArgs &event );
	// constant rotation z rand key up event
	bool Editor_Const_Rotation_Z_Rand_Key( const CEGUI::EventArgs &event );
	// direction base key up event
	bool Editor_Direction_Base_Key( const CEGUI::EventArgs &event );
	// direction rand key up event
	bool Editor_Direction_Rand_Key( const CEGUI::EventArgs &event );
	// scale base key up event
	bool Editor_Scale_Base_Key( const CEGUI::EventArgs &event );
	// scale rand key up event
	bool Editor_Scale_Rand_Key( const CEGUI::EventArgs &event );
	// horizontal gravity base key up event
	bool Editor_Horizontal_Gravity_Base_Key( const CEGUI::EventArgs &event );
	// horizontal gravity rand key up event
	bool Editor_Horizontal_Gravity_Rand_Key( const CEGUI::EventArgs &event );
	// vertical gravity base key up event
	bool Editor_Vertical_Gravity_Base_Key( const CEGUI::EventArgs &event );
	// vertical gravity rand key up event
	bool Editor_Vertical_Gravity_Rand_Key( const CEGUI::EventArgs &event );
	// todo : start rotation x/y/z rand, color, color_rand

	// Particle items
	typedef vector<cParticle *> ParticleList;
	ParticleList objects;

	// filename of the particle
	string filename;
	// emitter time to live
	float emitter_time_to_live;
	// emitter iteration interval
	float emitter_iteration_interval;
	// emitter object quota
	unsigned int emitter_quota;

	// velocity
	float vel, vel_rand;
	// start rotation z uses start direction
	bool start_rot_z_uses_direction;
	// constant rotation
	float const_rotx, const_roty, const_rotz;
	// constant rotation random modifier
	float const_rotx_rand, const_roty_rand, const_rotz_rand;
	// direction range
	float angle_start, angle_range;
	// size scaling
	float size_scale, size_scale_rand;
	// gravity
	float gravity_x, gravity_x_rand;
	float gravity_y, gravity_y_rand;
	// color random
	Color color_rand;
	// fading types todo : dest-color
	bool fade_size, fade_alpha, fade_color;
	// blending mode
	BlendingMode blending;

private:
	// time alive
	float emitter_living_time;
	// emit counter
	float emit_counter;
};

/* *** *** *** *** *** *** *** Animation Manager *** *** *** *** *** *** *** *** *** *** */

class cAnimation_Manager : public cObject_Manager<cAnimation>
{
public:
	cAnimation_Manager( void );
	virtual ~cAnimation_Manager( void );

	// Add an animation object with the given settings
	virtual void Add( cAnimation *animation );

	// Update the objects
	void Update( void );
	// Draw the objects
	void Draw( void );

	typedef vector<cAnimation *> AnimationList;
};

/* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */

// The Animation Manager
extern cAnimation_Manager *pAnimation_Manager;

/* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */

#endif
