#include "AutoGizmoC.h"

#include <assert.h>


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



AutoGizmoC::AutoGizmoC()
{
	// empty
}

AutoGizmoC::AutoGizmoC( EffectI* pParent, const char* szName, uint32 ui32Id ) :
	GizmoI( pParent, ui32Id )
{
	set_name( szName );
}

AutoGizmoC::AutoGizmoC( EditableI* pOriginal ) :
	GizmoI( pOriginal )
{
	// empty
}

AutoGizmoC::~AutoGizmoC()
{
	// Return if the gizmo is a clone.
	if( get_original() )
		return;

	for( uint32 i = 0; i < m_rParams.size(); i++ )
		m_rParams[i]->release();
}

AutoGizmoC*
AutoGizmoC::create_new( EffectI* pParent, const char* szName, uint32 ui32Id )
{
	return new AutoGizmoC( pParent, szName, ui32Id );
}

DataBlockI*
AutoGizmoC::create()
{
	return new AutoGizmoC;
}

DataBlockI*
AutoGizmoC::create( EditableI* pOriginal )
{
	return new AutoGizmoC( pOriginal );
}

void
AutoGizmoC::copy( EditableI* pEditable )
{
	GizmoI::copy( pEditable );

	m_rParams.clear();

	AutoGizmoC*	pGizmo = (AutoGizmoC*)pEditable;
	for( uint32 i = 0; i < pGizmo->m_rParams.size(); i++ )
	{
		ParamI*	pParam = (ParamI*)pGizmo->m_rParams[i]->duplicate();
		pParam->set_parent( this );
		m_rParams.push_back( pParam );
	}
}


void
AutoGizmoC::restore( EditableI* pEditable )
{
	GizmoI::restore( pEditable );

	m_rParams.clear();

	AutoGizmoC*	pGizmo = (AutoGizmoC*)pEditable;
	for( uint32 i = 0; i < pGizmo->m_rParams.size(); i++ )
		m_rParams.push_back( pGizmo->m_rParams[i] );
}

int32
AutoGizmoC::get_parameter_count()
{
	return m_rParams.size();
}

void
AutoGizmoC::add_parameter( ParamI* pParam )
{
	if( pParam )
		m_rParams.push_back( pParam ); 
}

void
AutoGizmoC::del_parameter( int32 i32Index )
{
	if( i32Index >= 0 && i32Index < (int32)m_rParams.size() )
		m_rParams.erase( m_rParams.begin() + i32Index );
}

ParamI*
AutoGizmoC::get_parameter( int32 i32Index )
{
	if( i32Index >= 0 && i32Index < (int32)m_rParams.size() )
		return m_rParams[i32Index];
	return 0;
}

ParamI*
AutoGizmoC::get_parameter_by_id( int32 i32Id )
{
	ParamI*	pParam = 0;
	for( uint32 i = 0; i < m_rParams.size(); i++ ) {
		if( m_rParams[i]->get_id() == i32Id ) {
			return m_rParams[i];
		}
	}

	return 0;
}


enum AutoGizmoChunksE {
	CHUNK_AUTOGIZMO_BASE	= 0x1000,
	CHUNK_AUTOGIZMO_PARAM	= 0x2000,
};

const uint32	AUTOGIZMO_VERSION = 1;

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

	// GizmoI stuff
	pSave->begin_chunk( CHUNK_AUTOGIZMO_BASE, AUTOGIZMO_VERSION );
		ui32Error = GizmoI::save( pSave );
	pSave->end_chunk();

	for( uint32 i = 0; i < m_rParams.size(); i++ ) {
		// position
		uint32	ui32Type = m_rParams[i]->get_type();
		pSave->begin_chunk( CHUNK_AUTOGIZMO_PARAM + m_rParams[i]->get_id(), AUTOGIZMO_VERSION );
			// save type
			ui32Error = pSave->write( &ui32Type, sizeof( ui32Type ) );
			// save data
			ui32Error = m_rParams[i]->save( pSave );
		pSave->end_chunk();
	}

	return IO_OK;
}

uint32
AutoGizmoC::load( FileIO::LoadC* pLoad )
{
	uint32	ui32Error = IO_OK;
	uint32	ui32Type;

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

		switch( pLoad->get_chunk_id() ) {
		case CHUNK_AUTOGIZMO_BASE:
			if( pLoad->get_chunk_version() == AUTOGIZMO_VERSION )
				ui32Error = GizmoI::load( pLoad );
			break;

		default:
			if( pLoad->get_chunk_id() >= CHUNK_AUTOGIZMO_PARAM ) {
				uint32	ui32ID = pLoad->get_chunk_id() - CHUNK_AUTOGIZMO_PARAM;

				ParamI*	pParam = 0;
				for( uint32 i = 0; i < m_rParams.size(); i++ ) {
					if( m_rParams[i]->get_id() == ui32ID ) {
						pParam = m_rParams[i];
						break;
					}
				}
				if( pParam ) {
					// load type
					ui32Error = pLoad->read( &ui32Type, sizeof( ui32Type ) );
					// load data
					if( ui32Type == pParam->get_type() )
						ui32Error = pParam->load( pLoad );
				}
			}
		}

		pLoad->close_chunk();

		if( ui32Error != IO_OK && ui32Error != IO_END )
			return ui32Error;
	}

	return ui32Error;
}
