#include "stdafx.h"
#include "PixelWhipPro.h"
#include "PP2KEffectLibrary.hpp"
#include <gosFX\DebrisCloud.hpp>
#include <Stuff\Stuff.hpp>
#include <MLR\MLRCulturShape.hpp>

using namespace Stuff;

extern CPixelWhipProApp theApp;

//------------------------------------------------------------------------------
//
PP2KEffectLibrary::PP2KEffectLibrary():
	gosFX::EffectLibrary(),
	m_shapeHash(23, NULL, true)
{
	HintFile = new NotationFile(theApp.TexturePath+"Textures.hint");
}

//------------------------------------------------------------------------------
//
PP2KEffectLibrary::~PP2KEffectLibrary()
{
	delete HintFile;

}

//------------------------------------------------------------------------------
//
MidLevelRenderer::MLRShape*
	PP2KEffectLibrary::UseShape(Stuff::MString& shape_file)
{
	Check_Object(this);
	Check_Object(&shape_file);
	Verify(shape_file);

	//
	//-------------------------------------------------------------------------
	// If we can find the shape file already in our hash, return it immediately
	//-------------------------------------------------------------------------
	//
	MidLevelRenderer::MLRShape *shape = m_shapeHash.Find(shape_file);
	if (shape)
	{
		Check_Object(shape);
		shape->AttachReference();
		return shape;
	}

	
	FileStream *file_stream=new FileStream(shape_file);

	//
	//------------------------------------------------------------------------
	// Now that we have the file loaded, make the shape out of it and stick it
	// in the hash
	//------------------------------------------------------------------------
	//
	int version = MidLevelRenderer::ReadMLRVersion(file_stream);
	OBB obb;

	*file_stream >> obb;


	if(version<14)
	{
		shape = MidLevelRenderer::MLRShape::Make(file_stream, version);
		Check_Object(shape);
	}
	else
	{
		RegisteredClass::ClassID class_id;
		*file_stream >> class_id;

		switch(class_id)
		{
			case MidLevelRenderer::MLRShapeClassID:
				shape = MidLevelRenderer::MLRShape::Make(file_stream, version);
			break;
			case MidLevelRenderer::MLRCulturShapeClassID:
				shape = MidLevelRenderer::MLRCulturShape::Make(file_stream, version);
			break;
		}
		Check_Object(shape);
	}

	bool mod=false;
	
	//Translate Textures here
	MidLevelRenderer::MLRPrimitiveBase *primitive;
	for(int prim=0;prim<shape->GetNum();prim++)
	{
		primitive = shape->Find(prim);

		MidLevelRenderer::MLRState state = primitive->GetReferenceState();

		CString tname(((*MidLevelRenderer::MLRTexturePool::Instance)[&state])->GetTextureName());
		if(TranslateName(tname, *HintFile))
		{
			MidLevelRenderer::MLRTexture *tex = MidLevelRenderer::MLRTexturePool::Instance->Add((LPCSTR)tname);
			state.SetTextureHandle(tex->GetTextureHandle());
			primitive->SetReferenceState(state);
			mod = true;
		}
	}

	if(mod || version<18)
	{
		PAUSE(("%s has been modified and rewritten",(char *)shape_file));

		FileStream *out_stream = new FileStream(shape_file);
		out_stream->Open(shape_file, FileStream::WriteOnly);
		MidLevelRenderer::WriteMLRVersion(out_stream);

		*out_stream << obb;

		shape->Save(out_stream);
		out_stream->Close();
	}

	m_shapeHash.AddValue(shape, shape_file);
	return shape;
}

//------------------------------------------------------------------------------
//
void
	PP2KEffectLibrary::LoadDebrisArray(
		gosFX::DebrisCloud__Specification *spec,
		Stuff::MString& debris_file
	)
{
	Check_Object(this);
	Check_Object(spec);
	Check_Object(&debris_file);
	Verify(debris_file);

	FileStream *file_stream=new FileStream(debris_file);

	//
	//------------------------------
	// Now start building the arrays
	//------------------------------
	//
	int gosfx_version = gosFX::ReadGFXVersion(file_stream);
	int mlr_version = MidLevelRenderer::ReadMLRVersion(file_stream);
	unsigned debris_count;
	*file_stream >> debris_count;

	spec->m_debrisPieces.SetLength(debris_count);
	spec->m_debrisPositions.SetLength(debris_count);
	spec->m_debrisSpheres.SetLength(debris_count);
	spec->m_debrisSeed.SetLength(debris_count);

	//
	//----------------------------------------------------------
	// Load in each shape and calculate a decent bounding volume
	//----------------------------------------------------------
	//
	Stuff::Scalar minRadius = 100000000000.0f, maxRadius = 0.0f;

	bool mod=false;
	unsigned i;
	for(i=0;i<debris_count;i++)
	{
		*file_stream >> spec->m_debrisPositions[i];

		*file_stream >> spec->m_debrisSpheres[i].center;
		*file_stream >> spec->m_debrisSpheres[i].radius;

		if(spec->m_debrisSpheres[i].radius < minRadius)
			minRadius = spec->m_debrisSpheres[i].radius;
		if(spec->m_debrisSpheres[i].radius > maxRadius)
			maxRadius = spec->m_debrisSpheres[i].radius;

		//
		//---------------
		// Load the shape
		//---------------
		//


		if(mlr_version<14)
		{
			spec->m_debrisPieces[i] = MidLevelRenderer::MLRShape::Make(file_stream, mlr_version);
		}
		else
		{
			RegisteredClass::ClassID class_id;
			*file_stream >> class_id;

			switch(class_id)
			{
				case MidLevelRenderer::MLRShapeClassID:
					spec->m_debrisPieces[i] = MidLevelRenderer::MLRShape::Make(file_stream, mlr_version);
				break;
				case MidLevelRenderer::MLRCulturShapeClassID:
					spec->m_debrisPieces[i] = MidLevelRenderer::MLRCulturShape::Make(file_stream, mlr_version);
				break;
			}
		}

		Check_Object(spec->m_debrisPieces[i]);

		//Translate Textures here
		MidLevelRenderer::MLRPrimitiveBase *primitive;
		for(int prim=0;prim<spec->m_debrisPieces[i]->GetNum();prim++)
		{
			primitive = spec->m_debrisPieces[i]->Find(prim);

			MidLevelRenderer::MLRState state = primitive->GetReferenceState();

			CString tname(((*MidLevelRenderer::MLRTexturePool::Instance)[&state])->GetTextureName());
			if(TranslateName(tname, *HintFile))
			{
				MidLevelRenderer::MLRTexture *tex = MidLevelRenderer::MLRTexturePool::Instance->Add((LPCSTR)tname);
				state.SetTextureHandle(tex->GetTextureHandle());
				primitive->SetReferenceState(state);
				mod = true;
			}
		}

	}

	Verify(maxRadius > minRadius);
	for(i=0;i<debris_count;i++)
	{
		spec->m_debrisSeed[i] = (spec->m_debrisSpheres[i].radius-minRadius)/(maxRadius-minRadius);
	}

	if(mod || mlr_version<18)
	{
		PAUSE(("%s has been modified and rewritten",(char *)debris_file));

		FileStream *out_stream = new FileStream(debris_file);
		out_stream->Open(debris_file, FileStream::WriteOnly);

		gosFX::WriteGFXVersion(out_stream);
		MidLevelRenderer::WriteMLRVersion(out_stream);

		*out_stream << debris_count;

		for(i=0;i<debris_count;i++)
		{
			*out_stream << spec->m_debrisPositions[i];

			*out_stream << spec->m_debrisSpheres[i].center;
			*out_stream << spec->m_debrisSpheres[i].radius;

			spec->m_debrisPieces[i]->Save(out_stream);
		}
		out_stream->Close();
	}
}
