//
// Asura_Chunk_ResourceFile_PC_Object.cpp
//
// Created by BM - 02/04/2003 15:56:20
//
// Copyright (C) 2003 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"

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

#include "Core/Asura_Material_System.h"
#include "FileAccess/Asura_FileAccess.h"
#include "Rendering/Asura_PlatformRenderObject.h"
#include "Rendering/Asura_Direct3D.h"
#include "Rendering/Asura_Direct3D_Caps.h"

bool Asura_Chunk_ResourceFile_PC_Object::Process( Asura_Handle hFile )
{	  
	Asura_Assert(Version<=ASURA_CHUNK_RESOURCEFILE_PC_OBJECT_VERSION,"Unrecognised chunk version");

	if(Version >= 4)
	{
		const bool bMaterialResponse = (Flags & ChunkFlag_MaterialResponse) != 0;
		#if defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM
		if(!bMaterialResponse)
		{
			Asura_Assert(0,"Attempting to load a non material response object into a material response build.\nThis will be skipped");
			return false;
		}
		#else
		if(bMaterialResponse)
		{
			Asura_Assert(0,"Attempting to load a material response object into a non material response build.\nThis will be skipped");
			return false;
		}
		#endif
	}
	
#if defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM
	#define ASURA_DIRECT3D_OBJECTVERTEX_TOUSE Asura_Direct3D_ObjectVertex_NormalMapped
#else
	#define ASURA_DIRECT3D_OBJECTVERTEX_TOUSE Asura_Direct3D_ObjectVertex
#endif

	// Check if there is enough room for a new object

	Asura_Hash_ID uHashID;
	Asura_FileAccess::ReadData(hFile, &uHashID, sizeof(u_int));
	
	Asura_Direct3D_ObjectRender_Handler&	xHandler	= Asura_Direct3D_ObjectRenderer::GetCurrentHandler();
	Asura_Direct3D_Object_Strip*			pxStrip		= xHandler.AddObjectStrip(uHashID);

	// JEB - 31 May 2006 16:32:21 - Added assert for objects that already exist
	Asura_Assertf(pxStrip != NULL, ("An Asura_Direct3D_Object_Strip with the specified uHashID (%u) already exists", uHashID));
	if(pxStrip)
	{
#if defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM
		pxStrip->m_bNormalMapped = true;
#endif
		u_int uNumberOfTriangles;
		u_int uNumberOfVertices;
		u_int uNumberOfIndices;
		#if defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM
		Asura_Hash_ID auMaterialResponseHashID[2] = {0,0};
		#else
		u_int uMaterialIndex;
		#endif

		{
			Asura_FileAccess::ReadData(hFile, &uNumberOfTriangles, sizeof(u_int));
			Asura_FileAccess::ReadData(hFile, &uNumberOfVertices, sizeof(u_int));
			Asura_FileAccess::ReadData(hFile, &uNumberOfIndices, sizeof(u_int));
			#if defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM
			Asura_FileAccess::ReadData(hFile, &auMaterialResponseHashID[0], sizeof(u_int));
			if(Version >= 4) Asura_FileAccess::ReadData(hFile, &auMaterialResponseHashID[1], sizeof(u_int));
			#else
			Asura_FileAccess::ReadData(hFile, &uMaterialIndex, sizeof(u_int));
			#endif
		
			pxStrip->m_uNumberOfTriangles = uNumberOfTriangles;
			pxStrip->m_uNumberOfVertices = uNumberOfVertices;
			pxStrip->m_uNumberOfIndices = uNumberOfIndices;

			#if defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM
				pxStrip->m_auMaterialResponseHashID[0] = auMaterialResponseHashID[0];
				pxStrip->m_auMaterialResponseHashID[1] = auMaterialResponseHashID[1];
			#else
				pxStrip->m_iMaterialIndex = Asura_Material_System::ConvertIndex(uMaterialIndex);
			#endif
		}

		int flags = D3DUSAGE_WRITEONLY;
			
		if (!Asura_Direct3D_Caps::HasHardwareVertexShaders())
		{
			flags |= D3DUSAGE_SOFTWAREPROCESSING;
		}

		// load in all vertex buffer data
		if(pxStrip->m_uNumberOfVertices)
		{
			// Create vertex and buffers for the strip
			
#ifdef ASURA_ASSERT
			HRESULT iResult = 
#endif
			Asura_Direct3D::D3DDevice->CreateVertexBuffer
			(
				pxStrip->m_uNumberOfVertices * sizeof( ASURA_DIRECT3D_OBJECTVERTEX_TOUSE),
				flags,
				0, 
				D3DPOOL_MANAGED,
				&(pxStrip->m_pxVertexBuffer),
				0
			);
			Asura_Assertf(iResult == D3D_OK, ("D3DDevice->CreateVertexBuffer() failed (%d)", iResult));

			// lock, fill in data and unlock
			Asura_Direct3D_ObjectVertex* pxVertexData;
			if (SUCCEEDED(pxStrip->m_pxVertexBuffer->Lock(0,sizeof( ASURA_DIRECT3D_OBJECTVERTEX_TOUSE) * pxStrip->m_uNumberOfVertices,(void**)&pxVertexData,0)))
			{
				Asura_FileAccess::ReadData(hFile, pxVertexData, sizeof( ASURA_DIRECT3D_OBJECTVERTEX_TOUSE) * pxStrip->m_uNumberOfVertices);
				pxStrip->m_pxVertexBuffer->Unlock();
			} else {
				Asura_Assert(false, "vertex buffer lock failed");
				Asura_FileAccess::SkipData(hFile, sizeof( ASURA_DIRECT3D_OBJECTVERTEX_TOUSE) * pxStrip->m_uNumberOfVertices);
			}

		}

		// load in all index buffer data
		if(pxStrip->m_uNumberOfIndices)
		{
			Asura_Direct3D::D3DDevice->CreateIndexBuffer
			(
				pxStrip->m_uNumberOfIndices * sizeof(unsigned short),
				flags,
				D3DFMT_INDEX16,
				D3DPOOL_MANAGED,
				&(pxStrip->m_pxIndexBuffer),
				0
			);
				
			unsigned short* pusIndexData;
			if (SUCCEEDED(pxStrip->m_pxIndexBuffer->Lock(0,sizeof(u_short) * pxStrip->m_uNumberOfIndices, (void**)&pusIndexData,0)))
			{
				Asura_FileAccess::ReadData(hFile, pusIndexData, sizeof(u_short) * pxStrip->m_uNumberOfIndices);

				pxStrip->m_pxIndexBuffer->Unlock();
			} else {
				Asura_Assert(false, "index buffer lock failed");
				Asura_FileAccess::SkipData(hFile, sizeof(u_short) * pxStrip->m_uNumberOfIndices);
			}
			
		}

		if(Version>=1)
		{
			Asura_Hash_ID uLODHash;
			Asura_FileAccess::ReadData(hFile, &pxStrip->m_fMinDistance, sizeof(float));
			Asura_FileAccess::ReadData(hFile, &uLODHash, sizeof(Asura_Hash_ID));

			if(uLODHash != ASURA_HASH_ID_UNSET)
			{
				//lower detail meshes appear earlier in the file , so we should be able to find it
				pxStrip->m_pxNextLowerStrip = xHandler.GetObjectStrip(uLODHash);
				Asura_Assert(pxStrip->m_pxNextLowerStrip,"Failed to find LOD shape");
			}
		}
	}
	
#undef ASURA_DIRECT3D_OBJECTVERTEX_TOUSE

	return true;
}
