#include "ElementProxyHeaders.hpp"

//
//############################################################################
//##########################    MLRPolygonProxy    ############################
//############################################################################
//

MemoryBlock*
	MLRPolygonProxy::AllocatedMemory = NULL;
MLRPolygonProxy::ClassData*
	MLRPolygonProxy::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRPolygonProxy::InitializeClass()
{
	Verify(!AllocatedMemory);
	AllocatedMemory =
		new MemoryBlock(
			sizeof(MLRPolygonProxy),
			10,
			10,
			"MLRPolygonProxy"
		);
	Register_Object(AllocatedMemory);

	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			MLRPolygonProxyClassID,
			"MLRPolygonProxy",
			PolygonProxy::DefaultData
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRPolygonProxy::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;

	Unregister_Object(AllocatedMemory);
	delete AllocatedMemory;
	AllocatedMemory = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRPolygonProxy::Destroy()
{
	Check_Object(this);
	Verify(referenceCount == 1);
	Verify(activeIndexProxies.IsEmpty());
	STOP(("Not implemented"));
	DetachReference();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRPolygonProxy::MLRPolygonProxy(
	ElementPolygonMeshProxy *mesh,
	int primitive_index,
	int polygon_index
):
	PolygonProxy(DefaultData, mesh),
	primitiveIndex(primitive_index),
	polygonIndex(polygon_index)
{
	Check_Pointer(this);
	Check_Object(mesh);

	//
	//------------------------------
	// Figure out our starting index
	//------------------------------
	//
	indexStart = 0;
	for (int i=0; i<polygonIndex; ++i)
	{
		indexStart +=
			mesh->indexCountArray[primitiveIndex][i];
	}
	Check_Object(this);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRPolygonProxy::~MLRPolygonProxy()
{
	Check_Object(this);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRPolygonProxy::TestInstance() const
{
	Verify(IsDerivedFrom(DefaultData));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
PolygonProxy*
	MLRPolygonProxy::UseNextPolygonProxy()
{
	Check_Object(this);
	ElementPolygonMeshProxy *mesh = GetPolygonMeshProxy();
	Check_Object(mesh);
	return mesh->GetPolygonProxy(primitiveIndex, polygonIndex+1);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
PolygonProxy*
	MLRPolygonProxy::UsePreviousPolygonProxy()
{
	Check_Object(this);
	ElementPolygonMeshProxy *mesh = GetPolygonMeshProxy();
	Check_Object(mesh);
	return mesh->GetPolygonProxy(primitiveIndex, polygonIndex-1);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
unsigned
	MLRPolygonProxy::UseIndexArray(DynamicArrayOf<IndexProxy*> *indices)
{
	Check_Object(this);
	Check_Object(indices);

	//
	//---------------------------------------
	// Get the count, then set the array size
	//---------------------------------------
	//
	ElementPolygonMeshProxy *mesh = GetPolygonMeshProxy();
	Check_Object(mesh);
	unsigned polygon_size =
		mesh->indexCountArray[primitiveIndex][polygonIndex];
	indices->SetLength(polygon_size);

	//
	//----------------------------
	// Now fill up the index array
	//----------------------------
	//
	for (unsigned index=0; index<polygon_size; ++index)
	{
		MLRVertexProxy *vertex = 
			MLRVertexProxy::MakeProxy(
				mesh,
				primitiveIndex,
				mesh->indexArray[primitiveIndex][indexStart + index]
			);
		Register_Object(vertex);
		(*indices)[index] =
			MLRIndexProxy::MakeProxy(
				this,
				vertex,
				index
			);
		Register_Object((*indices)[index]);
		vertex->DetachReference();
	}
	return polygon_size;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRPolygonProxy::AddToCollection(const char *collection)
{
	Check_Object(this);
	Check_Pointer(collection);

	SPEW(("shroom", "Group: %s", collection));
//	STOP(("Not implemented"));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRPolygonProxy::AddToCollections(MStringChain &collection_list)
{
	Check_Object(this);
	Check_Object(&collection_list);
	PolygonProxy::AddToCollections(collection_list);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRPolygonProxy::RemoveFromCollection(const char *collection)
{
	Check_Object(this);
	Check_Pointer(collection);

//	STOP(("Not implemented"));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRPolygonProxy::RemoveFromCollections(MStringChain &collection_list)
{
	Check_Object(this);
	Check_Object(&collection_list);
	PolygonProxy::RemoveFromCollections(collection_list);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRPolygonProxy::GetCollections(MStringChain *collection_list)
{
	Check_Object(this);
	Check_Object(collection_list);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	MLRPolygonProxy::IsMemberOf(const char *collection)
{
	Check_Object(this);
	Check_Pointer(collection);

//	STOP(("Not implemented"));
	return false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
unsigned
	MLRPolygonProxy::UseMultiState(MultiState *states)
{
	Check_Object(this);

	//
	//--------------------------------
	// Ask the primitive for its state
	//--------------------------------
	//
	ElementPolygonMeshProxy *mesh_proxy = GetPolygonMeshProxy();
	Check_Object(mesh_proxy);
	MLR_I_PMesh *mesh = mesh_proxy->GetPrimitive(primitiveIndex);
	Check_Object(mesh);

	//
	//--------------------------------------------
	// Make a state proxy for this polygon's state
	//--------------------------------------------
	//
	ElementSceneProxy *scene = mesh_proxy->GetSceneProxy();
	Check_Object(scene);
	MLRStatePoolProxy *library =
		Cast_Object(MLRStatePoolProxy*, scene->GetStateLibrary());


//	states = new MultiState;
	states->SetLength (mesh->GetNumPasses());

	for(unsigned i=0;i<states->GetLength();i++)
	{
		(*states)[i] =
			MLRStateProxy::MakeProxy(
				library,
				mesh->GetReferenceState(i)
			);

		Register_Object((*states)[i]);
	}
	return states->GetLength();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRPolygonProxy::SetStatesToMatch( const MultiState &states )
{
	STOP(("Not implemented yet!"));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
IndexProxy*
	MLRPolygonProxy::GetIndexProxy(unsigned index)
{
	Check_Object(this);
	ElementPolygonMeshProxy *mesh = GetPolygonMeshProxy();
	Check_Object(mesh);

	int count = mesh->indexCountArray[primitiveIndex][polygonIndex];

	if (index >= count)
	{
		return NULL;
	}

	MLRVertexProxy *vertex = 
		MLRVertexProxy::MakeProxy(
			mesh,
			primitiveIndex,
			mesh->indexArray[primitiveIndex][indexStart + index]
		);
	Register_Object(vertex);
	IndexProxy *proxy =
		MLRIndexProxy::MakeProxy(
			this,
			vertex,
			index
		);
	Register_Object(proxy);
	return proxy;
}
