#include "PajaTypes.h"
#include "Vector2C.h"
#include "Matrix2C.h"
#include "ColorC.h"
#include <vector>
#include "SWFChar.h"
#include "SWFFont.h"
#include "SWFDispList.h"


using namespace PajaTypes;

//
// Color transform
//

SWFCXFormC::SWFCXFormC( const PajaTypes::ColorC& rMult,
				const PajaTypes::ColorC& rAdd ):
	m_rMult( rMult ),
	m_rAdd( rAdd )
{
	// empty
}

SWFCXFormC::~SWFCXFormC()
{
	// empty
}

const ColorC&
SWFCXFormC::get_color_mult() const
{
	return m_rMult;
}

const ColorC&
SWFCXFormC::get_color_add() const
{
	return m_rAdd;
}

void
SWFCXFormC::set_color_mult( const ColorC& rMult )
{
	m_rMult = rMult;
}

void
SWFCXFormC::set_color_add( const ColorC& rAdd )
{
	m_rAdd = rAdd;
}


//
// Object reference
//

SWFObjectRefC::SWFObjectRefC( PajaTypes::uint32 ui32CharId, PajaTypes::uint32 ui32Depth,
								const PajaTypes::Matrix2C& rTM, const SWFCXFormC& rCXForm ) :
	m_ui32Depth( ui32Depth ),
	m_ui32CharId( ui32CharId ),
	m_rTM( rTM ),
	m_rCXForm( rCXForm )
{
	// empty
}

SWFObjectRefC::SWFObjectRefC( const SWFObjectRefC& rRef ) :
	m_ui32Depth( rRef.m_ui32Depth ),
	m_ui32CharId( rRef.m_ui32CharId ),
	m_rTM( rRef.m_rTM ),
	m_rCXForm( rRef.m_rCXForm ),
	m_ui32Frame( 0 )
{
	// empty
}

SWFObjectRefC::~SWFObjectRefC()
{
	// empty
}


uint32	
SWFObjectRefC::get_depth() const
{
	return m_ui32Depth;
}

uint32
SWFObjectRefC::get_char_id() const
{
	return m_ui32CharId;
}

const Matrix2C&
SWFObjectRefC::get_tm() const
{
	return m_rTM;
}

const SWFCXFormC&
SWFObjectRefC::get_cxform() const
{
	return m_rCXForm;
}

void
SWFObjectRefC::set_tm( const Matrix2C& rTM )
{
	m_rTM = rTM;
}

void
SWFObjectRefC::set_cxform( const SWFCXFormC& rCXForm )
{
	m_rCXForm = rCXForm;
}

void
SWFObjectRefC::set_frame( uint32 ui32Frame )
{
	m_ui32Frame = ui32Frame;
}

uint32
SWFObjectRefC::get_frame() const
{
	return m_ui32Frame;
}



//
// Display list
//

SWFDisplayListC::SWFDisplayListC()
{
	// empty
}

SWFDisplayListC::SWFDisplayListC( SWFDisplayListC& rList )
{
	for( uint32 i = 0; i < rList.m_rObjects.size(); i++ )
		m_rObjects.push_back( new SWFObjectRefC( *rList.m_rObjects[i] ) );
}

SWFDisplayListC::~SWFDisplayListC()
{
	for( uint32 i = 0; i < m_rObjects.size(); i++ ) {
		delete m_rObjects[i];
	}

	m_rObjects.clear();
}

void
SWFDisplayListC::move_object( uint32 ui32Depth, const Matrix2C& rTM, const SWFCXFormC& rCXForm, bool bHasTM, bool bHasCxForm )
{
	for( uint32 i = 0; i < m_rObjects.size(); i++ ) {
		if( m_rObjects[i]->get_depth() == ui32Depth ) {
			if( bHasTM )
				m_rObjects[i]->set_tm( rTM );
			if( bHasCxForm )
				m_rObjects[i]->set_cxform( rCXForm );
			break;
		}
	}
}

void
SWFDisplayListC::place_object( uint32 ui32CharId, uint32 ui32Depth, const Matrix2C& rTM, const SWFCXFormC& rCXForm )
{
	SWFObjectRefC*	pRef = new SWFObjectRefC( ui32CharId, ui32Depth, rTM, rCXForm );

	std::vector<SWFObjectRefC*>::iterator	rIt;

	for( rIt = m_rObjects.begin(); rIt != m_rObjects.end(); ++rIt ) {
		if( (*rIt)->get_depth() > ui32Depth ) {
			m_rObjects.insert( rIt, pRef );
			return;
		}
	}

	m_rObjects.push_back( pRef );
}

void
SWFDisplayListC::replace_object( uint32 ui32CharId, uint32 ui32Depth, const Matrix2C& rTM, const SWFCXFormC& rCXForm, bool bHasTM, bool bHasCxForm )
{
	SWFObjectRefC*	pRef = new SWFObjectRefC( ui32CharId, ui32Depth, rTM, rCXForm );

	std::vector<SWFObjectRefC*>::iterator	rIt;

	for( rIt = m_rObjects.begin(); rIt != m_rObjects.end(); ++rIt ) {
		if( (*rIt)->get_depth() == ui32Depth ) {

			// Copy needed attributes from old object
			if( !bHasTM )
				pRef->set_tm( (*rIt)->get_tm() );
			if( !bHasCxForm )
				pRef->set_cxform( (*rIt)->get_cxform() );

			// delete old
			delete (*rIt);

			// replace it with new
			(*rIt) = pRef;

			return;
		}
	}

	m_rObjects.push_back( pRef );
}

void
SWFDisplayListC::remove_object( uint32 ui32Depth, int32 i32TagId )
{
	std::vector<SWFObjectRefC*>::iterator	rIt;

	for( rIt = m_rObjects.begin(); rIt != m_rObjects.end(); ++rIt ) {
		if( (*rIt)->get_depth() == ui32Depth ) {
			delete (*rIt);
			m_rObjects.erase( rIt );
			return;
		}
	}
}

uint32
SWFDisplayListC::get_object_count() const
{
	return m_rObjects.size();
}

SWFObjectRefC*
SWFDisplayListC::get_object( uint32 ui32Idx )
{
	if( ui32Idx < m_rObjects.size() )
		return m_rObjects[ui32Idx];
	return 0;
}
