#include "AdeptHeaders.hpp"
#include "ResourceEffectLibrary.hpp"
#include "Application.hpp"
#include <gosFX\DebrisCloud.hpp>
#include <MLR\MLRCulturShape.hpp>

//------------------------------------------------------------------------------
//
ResourceEffectLibrary::ResourceEffectLibrary(bool preload):
	gosFX::EffectLibrary(preload),
	m_shapeHash(23, NULL, true)
{
}

//------------------------------------------------------------------------------
//
ResourceEffectLibrary::~ResourceEffectLibrary()
{
}

//------------------------------------------------------------------------------
//
MidLevelRenderer::MLRShape*
	ResourceEffectLibrary::UseShape(Stuff::MString& shape_file)
{
	Check_Object(this);
	Check_Object(&shape_file);
	Verify(shape_file.GetLength() > 0);

	//
	//------------------------------------------
	// If we aren't preloading, just return null
	//------------------------------------------
	//
	if (!m_preloadEffects)
		return NULL;

	//
	//-------------------------------------------------------------------------
	// 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;
	}

	//
	//----------------------------------------------------------------------
	// Otherwise, we need to open it up.  First we will look to see if it is
	// in the resource file already
	//----------------------------------------------------------------------
	//
	MString res_name = "Content\\Effects\\";
	res_name += shape_file;
	Resource stream(res_name);
	if (Application::BuildOK)
	{
		if (!stream.DoesResourceExist() || !stream.IsResourceUpToDate())
		{
			FileStream file_stream(res_name);
			FileDependencies dependencies;
			dependencies.AddDependency(&file_stream);
			stream.Save(&file_stream, &dependencies);
		}
	}
	else
		Verify(stream.DoesResourceExist());

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

	stream >> obb;

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

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

	Check_Object(shape);
	m_shapeHash.AddValue(shape, shape_file);
	return shape;
  
  
  
  
/*  int version = MidLevelRenderer::ReadMLRVersion(&stream);
	OBB obb;
	stream >> obb;
	shape = MidLevelRenderer::MLRShape::Make(&stream, version);
	Check_Object(shape);
	m_shapeHash.AddValue(shape, shape_file);
	return shape;
  */
}

//------------------------------------------------------------------------------
//
void
	ResourceEffectLibrary::LoadDebrisArray(
		gosFX::DebrisCloud__Specification *spec,
		Stuff::MString& debris_file
	)
{
	Check_Object(this);
	Check_Object(spec);
	Check_Object(&debris_file);
	Verify(debris_file.GetLength() > 0);

	//
	//------------------------------------------
	// If we aren't preloading, just return null
	//------------------------------------------
	//
	if (!m_preloadEffects)
		return;

	//
	//----------------------------------------------------------------------
	// Otherwise, we need to open it up.  First we will look to see if it is
	// in the resource file already
	//----------------------------------------------------------------------
	//
	MString res_name = "Content\\Effects\\";
	res_name += debris_file;
	Resource stream(res_name);
	if (Application::BuildOK)
	{
		if (!stream.DoesResourceExist() || !stream.IsResourceUpToDate())
		{
			FileStream file_stream(res_name);
			FileDependencies dependencies;
			dependencies.AddDependency(&file_stream);
			stream.Save(&file_stream, &dependencies);
		}
	}
	else
		Verify(stream.DoesResourceExist());

	//
	//------------------------------
	// Now start building the arrays
	//------------------------------
	//
	stream.LoadData();
	gosFX::ReadGFXVersion(&stream);
	int mlr_version = MidLevelRenderer::ReadMLRVersion(&stream);
	unsigned debris_count;
	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;

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

		stream >> spec->m_debrisSpheres[i].center;
		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(&stream, mlr_version);
		}
		else
		{
			RegisteredClass::ClassID class_id;
			stream >> class_id;

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

		Check_Object(spec->m_debrisPieces[i]);

	}

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