//////////////////////////////////////////////////////////////////
//
// Asura_Chunk_EnvironmentLBAABBTree.cpp
//
// Created by Andrew Weinkove - 11/08/05
//
// Chunk loaders for environment LBAABB. Based heavily on the AABB tree equivalent
//
// Copyright (C) 2005 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header.
#include "ChunkSystem/Asura_Chunk_EnvironmentLBAABBTree.h"

#include "ChunkSystem/Asura_Chunk_Loaders.h"
#include "ChunkSystem/Asura_Chunk_Macros.h"
#ifdef ASURA_TOOLS
#include "ChunkSystem/Asura_SaveBlock.h"
#endif
#include "ChunkSystem/Asura_Chunk_Stream.h"
#include "Core/Asura_LBAABB_Tree.h"
#include "Rendering/Asura_Module.h"

#ifdef ASURA_TOOLS
#include "Load&Save/Tools_AsrFileManager.h"
#endif


// For memset
#include <string.h>


static const int iENV_LBAABB_TREE_CUR_CHUNK_VERSION = 0;

bool Asura_Chunk_EnvironmentLBAABBTrees::Process (Asura_Chunk_Stream& xStream) const
{
	// check version
	if( Version > iENV_LBAABB_TREE_CUR_CHUNK_VERSION )
	{
		Asura_Assert( false, "Environment LBAABB chunk version is too new. You need a new build.");
		return false;
	}
	#ifdef ASURA_TOOLS
	if(Tools_AsrFileManager::IsUsingMultipleAsrFiles())
	{
		//If the environment is split across multiple asr files then the LBAABB trees from each
		//file won't be much use for the environment as a whole. So skip them and allow them
		//to be recalculated later.
		//RAR 18/10/2007
		return false;
	}
	#endif


	Asura_ResourcePushType(ASURA_RESOURCE_MODULE);
	{
		Asura_Module_Handler&	xHandler			= Asura_Module_System::GetCurrentHandler();
		if(xHandler.HasLBAABBModuleTree())
		{
			Asura_Assert(0, "LBAABB module tree has already been set up.\nThis may happen when loading a skin file that has been exported as an environment by mistake.");
			Asura_ResourcePopType();
			return false;
		}
		Asura_LBAABB_Tree*		pxLBAABBModuleTree	= xHandler.CreateLBAABBModuleTree();

		// Main module tree...
		pxLBAABBModuleTree->ReadHeaderFromChunkStream	(xStream);

		if (pxLBAABBModuleTree->GetNumberOfDoubleNodes())
		{
			u_int	uNumberOfNodes	= pxLBAABBModuleTree->GetNumberOfDoubleNodes ();

			Asura_ResourceAllocateArray(pxLBAABBModuleTree->m_pxNodes, uNumberOfNodes);

			for (u_int n = 0; n < uNumberOfNodes; n++)
			{
				pxLBAABBModuleTree->m_pxNodes [n].ReadFromChunkStream	(xStream);
			}
		}
		else
		{
			pxLBAABBModuleTree->m_pxNodes = NULL;
		}

		u_int*	puModuleTreeLBAABBConversionArray	= xHandler.CreateModuleTreeLBAABBConversionArray(pxLBAABBModuleTree->GetNumberOfNodes() + 1);

		Asura_ReadFromStream_Array_Wrapper<u_int>	xArray (pxLBAABBModuleTree->GetNumberOfNodes() + 1, puModuleTreeLBAABBConversionArray);

		xStream >> xArray;
	}
	Asura_ResourcePopType();

#ifdef ASURA_TOOLS
	// (AW - 11.08.2005) - Copied from Asura_Chunk_EnvironmentAABBTree. Isn't reading
	// all this data pretty pointless in tools, then?
	Asura_Module_System::InvalidateAllCollisionData();
#endif //#ifdef ASURA_TOOLS
	return true;
}

bool Asura_Chunk_EnvironmentLBAABBTrees::Process(Asura_Handle iFileHandle) const
{
	Asura_Chunk_File_Stream	xStream (iFileHandle);


	// Call the other process function...

	return	(Process(xStream));
}

#ifdef ASURA_TOOLS

bool Asura_Chunk_EnvironmentLBAABBTrees::Create (Asura_Chunk_Stream& xStream)
{
	const Asura_Module_Handler&	xHandler	= Asura_Module_System::GetCurrentHandler();

	if(Tools_AsrFileManager::IsUsingMultipleAsrFiles() && !Tools_Level_Export::IsExport())
	{
		//Skipping this when using multiple asr files for an environment , because it should
		//probably just save the data that goes with the meshes in that file , but that is more
		//hassle than its worth , since we are going to ignore it anyway.
		//RAR 18/10/2007
		return true;
	}
	

		
	// Write the chunk-data...
	xStream.WriteChunk_Start	(ASURA_CHUNK_ENVIRONMENT_LBAABBTREES, iENV_LBAABB_TREE_CUR_CHUNK_VERSION, 0);

	// Module tree.
	xHandler.m_pxLBAABBModuleTree->WriteHeaderToChunkStream(xStream, -Tools_Level_Export::GetExportCentre());
	for (u_int i=0;i<xHandler.m_pxLBAABBModuleTree->GetNumberOfDoubleNodes();i++)
	{
		xHandler.m_pxLBAABBModuleTree->m_pxNodes[i].WriteToChunkStream(xStream);
	}
	Asura_WriteToStream_Array_Wrapper<u_int> xArrayWrapper(xHandler.m_pxLBAABBModuleTree->GetNumberOfNodes() + 1, xHandler.m_puModuleTreeLBAABBConversionArray);
	xStream << xArrayWrapper;

	xStream.WriteChunk_End	();
	return true;
}

#endif //#ifdef ASURA_TOOLS
