#include "PajaTypes.h"
#include "Vector3C.h"
#include "ControllerC.h"
#include "ParticleSystemC.h"

using namespace Composition;
using namespace PajaTypes;
using namespace FileIO;


ParticleSystemC::ParticleSystemC() :
	m_rPos( 0, 0, 0 ),
	m_rTgt( 0, 0, 1 ),
	m_f32Multiplier( 1 ),
	m_pPosCont( 0 ),
	m_pTgtCont( 0 ),
	m_pColorCont( 0 ),
	m_pMultCont( 0 )
{
	// empty
}

ParticleSystemC::~ParticleSystemC()
{
	if( m_pPosCont ) m_pPosCont->release();
	if( m_pTgtCont ) m_pTgtCont->release();
	if( m_pColorCont ) m_pColorCont->release();
	if( m_pMultCont ) m_pMultCont->release();
}

void
ParticleSystemC::set_position( const Vector3C& rPos )
{
	m_rPos = rPos;
}

const
Vector3C&
ParticleSystemC::get_position()
{
	return m_rPos;
}

void
ParticleSystemC::set_target_position( const Vector3C& rPos )
{
	m_rTgt = rPos;
}

const
Vector3C&
ParticleSystemC::get_target_position()
{
	return m_rTgt;
}


void
ParticleSystemC::set_color( const ColorC& rVal )
{
	m_rColor = rVal;
}

const
ColorC&
ParticleSystemC::get_color()
{
	return m_rColor;
}

void
ParticleSystemC::set_multiplier( float32 f32Val )
{
	m_f32Multiplier = f32Val;
}

float32
ParticleSystemC::get_multiplier()
{
	return m_f32Multiplier;
}


void
ParticleSystemC::eval_state( int32 i32Time )
{
	if( m_pPosCont )
		m_pPosCont->get_value( m_rPos, i32Time ); 

	if( m_pTgtCont )
		m_pTgtCont->get_value( m_rTgt, i32Time ); 

	if( m_pColorCont )
		m_pColorCont->get_value( m_rColor, i32Time ); 

	if( m_pMultCont )
		m_pMultCont->get_value( m_f32Multiplier, i32Time ); 

}

void
ParticleSystemC::set_position_controller( ControllerC* pCont )
{
	m_pPosCont = pCont;
}

ControllerC*
ParticleSystemC::get_position_controller()
{
	return m_pPosCont;
}

void
ParticleSystemC::set_target_position_controller( ControllerC* pCont )
{
	m_pTgtCont = pCont;
}

ControllerC*
ParticleSystemC::get_target_position_controller()
{
	return m_pTgtCont;
}

void
ParticleSystemC::set_color_controller( ControllerC* pCont )
{
	m_pColorCont = pCont;
}

ControllerC*
ParticleSystemC::get_color_controller()
{
	return m_pColorCont;
}

void
ParticleSystemC::set_multiplier_controller( ControllerC* pCont )
{
	m_pMultCont = pCont;
}

ControllerC*
ParticleSystemC::get_multiplier_controller()
{
	return m_pMultCont;
}



enum ParticleSystemChunksE {
	CHUNK_PSYSTEM_BASE			= 0x1001,
	CHUNK_PSYSTEM_CONT_POS		= 0x2000,
	CHUNK_PSYSTEM_CONT_TGT		= 0x2001,
	CHUNK_PSYSTEM_CONT_COLOR	= 0x2002,
	CHUNK_PSYSTEM_CONT_MULT		= 0x2003,
};

const uint32	PSYSTEM_VERSION = 1;


uint32
ParticleSystemC::save( SaveC* pSave )
{
	uint32	ui32Error = IO_OK;

	std::string	sStr;
	float32	f32Temp[3];

	// camera base (static)
	pSave->begin_chunk( CHUNK_PSYSTEM_BASE, PSYSTEM_VERSION );
		// position
		f32Temp[0] = m_rPos[0];
		f32Temp[1] = m_rPos[1];
		f32Temp[2] = m_rPos[2];
		ui32Error = pSave->write( f32Temp, sizeof( f32Temp ) );

		// target pos
		f32Temp[0] = m_rTgt[0];
		f32Temp[1] = m_rTgt[1];
		f32Temp[2] = m_rTgt[2];
		ui32Error = pSave->write( f32Temp, sizeof( f32Temp ) );

		// color
		f32Temp[0] = m_rColor[0];
		f32Temp[1] = m_rColor[1];
		f32Temp[2] = m_rColor[2];
		ui32Error = pSave->write( f32Temp, sizeof( f32Temp ) );

		// mulltiplier
		ui32Error = pSave->write( &m_f32Multiplier, sizeof( m_f32Multiplier ) );

	pSave->end_chunk();

	// controllers
	if( m_pPosCont ) {
		pSave->begin_chunk( CHUNK_PSYSTEM_CONT_POS, PSYSTEM_VERSION );
			m_pPosCont->save( pSave );
		pSave->end_chunk();
	}

	if( m_pTgtCont ) {
		pSave->begin_chunk( CHUNK_PSYSTEM_CONT_TGT, PSYSTEM_VERSION );
			m_pTgtCont->save( pSave );
		pSave->end_chunk();
	}

	if( m_pColorCont ) {
		pSave->begin_chunk( CHUNK_PSYSTEM_CONT_COLOR, PSYSTEM_VERSION );
			m_pColorCont->save( pSave );
		pSave->end_chunk();
	}

	if( m_pMultCont ) {
		pSave->begin_chunk( CHUNK_PSYSTEM_CONT_MULT, PSYSTEM_VERSION );
			m_pMultCont->save( pSave );
		pSave->end_chunk();
	}


	return ui32Error;
}

uint32
ParticleSystemC::load( LoadC* pLoad )
{
	uint32	ui32Error = IO_OK;
	char	szStr[256];
	float32	f32Temp[3];

	while( (ui32Error = pLoad->open_chunk()) == IO_OK ) {

		switch( pLoad->get_chunk_id() ) {
		case CHUNK_PSYSTEM_BASE:
			{
				if( pLoad->get_chunk_version() == PSYSTEM_VERSION ) {
					// position
					ui32Error = pLoad->read( f32Temp, sizeof( f32Temp ) );
					m_rPos[0] = f32Temp[0];
					m_rPos[1] = f32Temp[1];
					m_rPos[2] = f32Temp[2];

					// target pos
					ui32Error = pLoad->read( f32Temp, sizeof( f32Temp ) );
					m_rTgt[0] = f32Temp[0];
					m_rTgt[1] = f32Temp[1];
					m_rTgt[2] = f32Temp[2];

					// color
					ui32Error = pLoad->read( f32Temp, sizeof( f32Temp ) );
					m_rColor[0] = f32Temp[0];
					m_rColor[1] = f32Temp[1];
					m_rColor[2] = f32Temp[2];

					// mult
					ui32Error = pLoad->read( &m_f32Multiplier, sizeof( m_f32Multiplier ) );
				}
			}
			break;

		case CHUNK_PSYSTEM_CONT_POS:
			{
				if( pLoad->get_chunk_version() == PSYSTEM_VERSION ) {
					ControllerC*	pCont = ControllerC::create_new( CONT_TYPE_VECTOR3 );	// the type doesnt matter
					ui32Error = pCont->load( pLoad );
					m_pPosCont = pCont;
				}
			}
			break;

		case CHUNK_PSYSTEM_CONT_TGT:
			{
				if( pLoad->get_chunk_version() == PSYSTEM_VERSION ) {
					ControllerC*	pCont = ControllerC::create_new( CONT_TYPE_VECTOR3 );	// the type doesnt matter
					ui32Error = pCont->load( pLoad );
					m_pTgtCont = pCont;
				}
			}
			break;

		case CHUNK_PSYSTEM_CONT_COLOR:
			{
				if( pLoad->get_chunk_version() == PSYSTEM_VERSION ) {
					ControllerC*	pCont = ControllerC::create_new( CONT_TYPE_VECTOR3 );	// the type doesnt matter
					ui32Error = pCont->load( pLoad );
					m_pColorCont = pCont;
				}
			}
			break;

		case CHUNK_PSYSTEM_CONT_MULT:
			{
				if( pLoad->get_chunk_version() == PSYSTEM_VERSION ) {
					ControllerC*	pCont = ControllerC::create_new( CONT_TYPE_VECTOR3 );	// the type doesnt matter
					ui32Error = pCont->load( pLoad );
					m_pMultCont = pCont;
				}
			}
			break;

		default:
			assert( 0 );
		}

		pLoad->close_chunk();

		if( ui32Error != IO_OK && ui32Error != IO_END ) {
			OutputDebugString( "plaa1\n" );
			return ui32Error;
		}
	}

	if( ui32Error != IO_OK && ui32Error != IO_END ) {
		OutputDebugString( "plaa2\n" );
		return ui32Error;
	}

	return IO_OK;
}
