//////////////////////////////////////////////////////////////////////////////
//
// Axon_Chunk_AnimTemplates.cpp
//
// Copyright (c) 2006 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

#include "Core/Asura.h"

#ifdef ASURA_USE_AXON

// This file's header.
#include "Axon_Chunk_AnimTemplates.h"

//Asura
#include "ChunkSystem/Asura_Chunk_Stream.h"
#include "ChunkSystem/Asura_SaveBlock.h"
#ifdef ASURA_TOOLS
#include "FileAccess/Asura_FileAccess.h"
#endif

//Axon
#include "AnimTemplates/Axon_Gamescene_AnimTemplates.h"
#include "AnimTemplates/Axon_Gamescene_AnimTemplate_System.h"

//////////////////////////////////////////////////////////////////////////////
//
// Axon_Chunk_AnimTemplates
//
//////////////////////////////////////////////////////////////////////////////

bool Axon_Chunk_AnimTemplates::Process( Asura_Handle hFile ) const
{
	Asura_Chunk_File_Stream	xStream( hFile );

	bool bOk = true;
	if ( Version == iCURRENT_VERSION )
	{
		bOk &= ReadTemplatesIn( xStream );
		bOk &= ReadPackagesIn( xStream );
	}
	else if ( Version == 0 )
	{
		bOk &= ReadTemplatesIn( xStream );
	}
	else
	{
		Asura_Assertf( false, ( "Axon_Chunk_AnimTemplates::Process - unhandled chunk version (%d)", Version ) );
		bOk = false;
	}

	return bOk;
}

#ifdef ASURA_TOOLS
bool Axon_Chunk_AnimTemplates::SaveAnimTemplateAndPackageData( const char* szFilename )
{
	Asura_SaveBlock xSaveBlock;

	Asura_Chunk_SaveBlock_Stream xStream( &xSaveBlock );
	xStream.WriteChunk_Start( AXON_CHUNK_ANIMTEMPLATES, iCURRENT_VERSION, 0 );

	// Templates.
	const int iNumTemplates = Axon_Gamescene_AnimTemplate_System::GetNumAnimTemplates();
	xStream << iNumTemplates;

	for ( Asura_TemplateHashTree_SaveIterator xSaveIter( iNumTemplates ); !xSaveIter.Done(); xSaveIter.Next() )
	{
		const Axon_Gamescene_AnimTemplate* pxTemplate =
			*Axon_Gamescene_AnimTemplate_System::s_xAnimTemplatePtrTree.GetDataByIndex( xSaveIter.GetCurrent() );
		xStream << pxTemplate->GetType();
		pxTemplate->WriteToChunkStream( xStream );
	}

	// Packages.
	const int iNumPackages = Axon_Gamescene_AnimTemplate_System::GetNumAnimPackages();
	xStream << iNumPackages;

	for ( Asura_TemplateHashTree_SaveIterator xSaveIter( iNumPackages ); !xSaveIter.Done(); xSaveIter.Next() )
	{
		const Axon_GS2_AnimPackage* pxPackage =
			*Axon_Gamescene_AnimTemplate_System::s_xAnimPackagePtrTree.GetDataByIndex( xSaveIter.GetCurrent() );
		pxPackage->WriteToChunkStream( xStream );
	}

	xStream.WriteChunk_End();

	xSaveBlock.AddAsuraTerminator();
	return xSaveBlock.SaveFile( szFilename, true );
}

bool Axon_Chunk_AnimTemplates::SaveAnimTemplateData( const char* szFilename, const Axon_Gamescene_AnimTemplate& xAnimTemplate )
{
	Asura_SaveBlock xSaveBlock;
	Asura_Chunk_SaveBlock_Stream xStream( &xSaveBlock );
	xStream.WriteChunk_Start( AXON_CHUNK_ANIMTEMPLATES, iCURRENT_VERSION, 0 );

	// Templates.
	xStream << 1;

	xStream << xAnimTemplate.GetType();
	xAnimTemplate.WriteToChunkStream( xStream );

	// Packages.
	xStream << 0;

	xStream.WriteChunk_End();

	xSaveBlock.AddAsuraTerminator();
	return xSaveBlock.SaveFile( szFilename, true );
}

bool Axon_Chunk_AnimTemplates::SaveAnimPackageData( const char* szFilename, const Axon_GS2_AnimPackage& xAnimPackage )
{
	Asura_SaveBlock xSaveBlock;
	Asura_Chunk_SaveBlock_Stream xStream( &xSaveBlock );
	xStream.WriteChunk_Start( AXON_CHUNK_ANIMTEMPLATES, iCURRENT_VERSION, 0 );

	// Templates.
	xStream << 0;

	// Packages.
	xStream << 1;
	xAnimPackage.WriteToChunkStream( xStream );

	xStream.WriteChunk_End();

	xSaveBlock.AddAsuraTerminator();
	return xSaveBlock.SaveFile( szFilename, true );
}
#endif // ASURA_TOOLS

bool Axon_Chunk_AnimTemplates::ReadTemplatesIn( Asura_Chunk_File_Stream& xStream )
{
	int iNumTemplates;
	xStream >> iNumTemplates;
	for ( int i = 0; i < iNumTemplates; ++i )
	{
		u_int uTemplateType;
		xStream >> uTemplateType;

		Axon_Gamescene_AnimTemplate* pxTemplate = NULL;
		switch ( uTemplateType )
		{
		    case AXON_ATT_STATIC:
			{
				pxTemplate = new Axon_Gamescene_StaticAnimTemplate();
				pxTemplate->ReadFromChunkStream( xStream );
				break;
			}

		    case AXON_ATT_LOOPINGMOVEMENT:
			{
				pxTemplate = new Axon_Gamescene_LoopingAnimTemplate();
				pxTemplate->ReadFromChunkStream( xStream );
				break;
			}

		    case AXON_ATT_RIGIDMOVEMENT:
			{
				pxTemplate = new Axon_Gamescene_RigidAnimTemplate();
				pxTemplate->ReadFromChunkStream( xStream );
				break;
			}

		    case AXON_ATT_FIDGETBEHAVIOUR:
			{
				pxTemplate = new Axon_Gamescene_FidgetAnimTemplate();
				pxTemplate->ReadFromChunkStream( xStream );
				break;
			}

		    default:
			{
				Asura_Assertf( false, ( "Axon_Chunk_AnimTemplates::Process - unknown animation template type %u", uTemplateType ) );
				return false;
			}
		}

		if ( Axon_Gamescene_AnimTemplate_System::s_xAnimTemplatePtrTree.AddNode( pxTemplate->GetUniqueID(), pxTemplate ) )
		{
			#ifdef ASURA_TOOLS
			// Make sure the template name reflects what file the template was in.
			//## todo - This code can be simplified once the AnimTemp.asr file has disappeared in all projects.
			//##	  - At this stage the template chunk can be updated to no longer save out the filename.
			Asura_String xFullFileName( Asura_FileAccess::GetFilename( xStream.GetFileHandle() ) );
			Asura_String xPath;
			Asura_String xFileName;
			xFullFileName.SplitFilename( &xPath, &xFileName, NULL );
			// If this has been loaded from the AnimTemp.asr file then don't override the file name.
			if ( xFileName != "AnimTemp" )
			{
				pxTemplate->SetName( xFileName );
				pxTemplate->SetPath( Asura_FileAccess::PlatformRemoveNetworkOrExecutableDir( xPath.GetString() ) );
			}
			#endif
		}
		else
		{
			// If we can't add it then it's either a duplicate, or a unique ID clash.
			#ifdef ASURA_TOOLS
			#ifdef ASURA_ASSERT
			const Asura_String& xStr1 = pxTemplate->GetName();
			const Asura_String& xStr2 = Axon_Gamescene_AnimTemplate_System::GetAnimTemplateByID( pxTemplate->GetUniqueID() )->GetName();
			Asura_Assertf( false, ( "Anim Templates: found and discarded duplicate template '%s'.\n"
				"Clashes with template '%s'.",
				xStr1.GetString(),
				xStr2.GetString() ) );
			#endif
			#endif
			delete pxTemplate;
		}
	}

	return true;
}

bool Axon_Chunk_AnimTemplates::ReadPackagesIn( Asura_Chunk_File_Stream& xStream )
{
	int iNumPackages;
	xStream >> iNumPackages;
	for ( int i = 0; i < iNumPackages; ++i )
	{
		Axon_GS2_AnimPackage* pxPackage = Axon_Gamescene_AnimTemplate_System::s_pxThis->CreateAnimPackage();
		pxPackage->ReadFromChunkStream( xStream );
		if ( Axon_Gamescene_AnimTemplate_System::s_xAnimPackagePtrTree.AddNode( pxPackage->GetUniqueID(), pxPackage ) )
		{
			#ifdef ASURA_TOOLS
			// Make sure the package name reflects what file the package was in.
			//## todo - This code can be simplified once the AnimTemp.asr file has disappeared in all projects.
			//##	  - At this stage the template chunk can be updated to no longer save out the filename.
			Asura_String xFullFileName( Asura_FileAccess::GetFilename( xStream.GetFileHandle() ) );
			Asura_String xPath;
			Asura_String xFileName;
			xFullFileName.SplitFilename( &xPath, &xFileName, NULL );
			// If this has been loaded from the AnimTemp.asr file then don't override the file name.
			if ( xFileName != "AnimTemp" )
			{
				pxPackage->SetName( xFileName );
				pxPackage->SetPath( Asura_FileAccess::PlatformRemoveNetworkOrExecutableDir( xPath.GetString() ) );
			}
			#endif
		}
		else
		{
			// If we can't add it then it's either a duplicate, or a unique ID clash.
			#ifdef ASURA_TOOLS
			const Asura_String& xStr1 = pxPackage->GetName();
			const Asura_String& xStr2 = Axon_Gamescene_AnimTemplate_System::GetAnimTemplateByID( pxPackage->GetUniqueID() )->GetName();
			Asura_Assertf( false, ( "Anim Templates: found and discarded duplicate package '%s'.\n"
				"Clashes with package '%s'.",
				xStr1.GetString(),
				xStr2.GetString() ) );
			#endif
			delete pxPackage;
		}
	}

	return true;
}

//////////////////////////////////////////////////////////////////////////////
//
//
//////////////////////////////////////////////////////////////////////////////

#endif // ASURA_USE_AXON
