#include "ProxyHeaders.hpp"

char	*GetInfoProcess::names[InfoBitCount] = 
{
	"SceneProxy",
	"GroupProxy",
	"ChildProxy",
	"PolyMeshProxy",
	"PolygonProxy",
	"StateProxy",
	"TextureProxy",
	"TextureLibraryProxy"
};

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GetInfoProcess::Reset()
{
	int i;

	for(i=0;i<InfoBitCount;i++)
	{
		nrOfProcessedItems[i] = 0;
	}

	hierarchyInfoLevel = 0;
	hierarchyInfoSibling = 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GetInfoProcess::InfoCallback(int mode)
{
	int i;
	int mask = 1;

	for(i=0;i<InfoBitCount;i++)
	{
		if(mode & mask)
		{
			nrOfProcessedItems[i]++;
		}
		mask <<= 1;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GetInfoProcess::TellWhatYouKnow()
{
	int i;

	(*stream) << "\r\n" << "The Infoprocess has:" << "\r\n";

	for(i=0;i<InfoBitCount;i++)
	{
		if(nrOfProcessedItems[i] > 0)
		{
			(*stream) << nrOfProcessedItems[i] << " " << names[i] << " " << "processed." << "\r\n";
		}
	}
	(*stream) << "\r\n";
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GetInfoProcess::TellMyName(Stuff::MString *name, int mode)
{
	int i;

	for(i=0;i<hierarchyInfoLevel;i++)
	{
		(*stream) << '\t';
	}

	if(name->GetLength())
	{
		(*stream) << *name;
	}
	else
	{
		int mask = 1;

		for(i=0;i<InfoBitCount;i++)
		{
			if(mode & mask)
			{
				break;
			}
			mask <<= 1;
		}
		Verify(i<InfoBitCount);
		(*stream) << names[i] << " #" << nrOfProcessedItems[i];
	}

	if(	mode & InfoSceneMode ||
		mode & InfoGroupMode ||
		mode & InfoChildMode ||
		mode & InfoPolyMeshMode
	)
	{
		(*stream) << " " << hierarchyInfoLevel << " " << hierarchyInfoSibling;
	}

	(*stream) << ":" << "\r\n";
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GetInfoProcess::TalkAboutATexLibrary(const char *path, const char *ext)
{
	(*stream) << "Texture path: \"" << path << "\" Extention: \"" << ext << "\"\n";
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GetInfoProcess::TalkAboutAMesh(int nrOfPolys, int nrOfVertices, int nrOfIndices, int nrOfStates)
{
	int i;

	for(i=0;i<hierarchyInfoLevel;i++)
	{
		(*stream) << '\t';
	}

	(*stream)	<< "P: " << nrOfPolys
				<< " V: " << nrOfVertices
				<< " I: " << nrOfIndices
				<< " I/V: " << (Scalar)nrOfIndices/(Scalar)nrOfVertices
				<< " S: " << nrOfStates
				<< "\r\n";
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	TextureProxy::GetInfo(
		GetInfoProcess *process
	)
{
	Check_Object(this);
	Check_Object(process);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->InfoCallback(GetInfoProcess::InfoTextureMode);
	if (!process->continueProcess)
		return;


	//
	//-------------
	// Get the info
	//-------------
	//
	MString name;
	GetName(&name);

	process->TellMyName(&name, GetInfoProcess::InfoTextureMode);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	StateProxy::GetInfo(
		GetInfoProcess *process
	)
{
	Check_Object(this);
	Check_Object(process);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->InfoCallback(GetInfoProcess::InfoStateMode);
	if (!process->continueProcess)
		return;

	//
	//-------------
	// Get the info
	//-------------
	//
	MString name;
	GetName(&name);

	process->TellMyName(&name, GetInfoProcess::InfoStateMode);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GroupProxy::GetInfo(
		GetInfoProcess *process
	)
{
	Check_Object(this);
	Check_Object(process);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->InfoCallback(GetInfoProcess::InfoGroupMode);
	if (!process->continueProcess)
		return;


	//
	//-------------
	// Get the info
	//-------------
	//
	MString name;
	GetName(&name);

	process->TellMyName(&name, GetInfoProcess::InfoGroupMode);

	//
	//---------------------------------------------------------
	// For each child in the source, copy it to the destination
	//---------------------------------------------------------
	//

	int nrOfChildren = 0;
	process->IncHierarchyLevel();

	ChildProxy *child = UseFirstChildProxy();
	while (child)
	{
		Check_Object(child);

		process->SetHierarchySibling(nrOfChildren++);
		child->GetInfo(process);

		ChildProxy *next = child->UseNextSiblingProxy();
		child->DetachReference();
		
		if (process->continueProcess)
			child = next;
		else
		{
			if (child)
				child->DetachReference();
			break;
		}
	}
	process->DecHierarchyLevel();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ChildProxy::GetInfo(
		GetInfoProcess *process
	)
{
	Check_Object(this);
	Check_Object(process);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->InfoCallback(GetInfoProcess::InfoChildMode);
	if (!process->continueProcess)
		return;

	//
	//-------------
	// Get the info
	//-------------
	//
	MString name;
	GetName(&name);

	process->TellMyName(&name, GetInfoProcess::InfoChildMode);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	PolygonMeshProxy::GetInfo(
		GetInfoProcess *process
	)
{
	Check_Object(this);
	Check_Object(process);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->InfoCallback(GetInfoProcess::InfoPolyMeshMode);
	if (!process->continueProcess)
		return;

	//
	//-------------
	// Get the info
	//-------------
	//
	MString name;
	GetName(&name);

	process->TellMyName(&name, GetInfoProcess::InfoPolyMeshMode);

	//
	//---------------------------------------------------------------
	// Get the polygons of the source mesh, then analyze their states
	//---------------------------------------------------------------
	//
	DynamicArrayOf<PolygonProxy*> source_polygons;
	DynamicArrayOf<VertexProxy*> source_vertices;
	DynamicArrayOf<IndexProxy*> source_indices;

	unsigned i, total_polys = UsePolygonArray(&source_polygons);
	unsigned total_vertices = UseVertexArray(&source_vertices);

	Verify(total_polys == source_polygons.GetLength());
	Verify(total_vertices == source_vertices.GetLength());

	//
	//-----------------------------------------------------------------------
	// We have to evaluate each polygon within the mesh to see how many have
	// unique texture/material combinations, so set up arrays to hold proxies
	// and matching indices
	//-----------------------------------------------------------------------
	//
	DynamicArrayOf<unsigned> match;
	DynamicArrayOf<unsigned> count;
	DynamicArrayOf<MultiState*> source_states;

	unsigned unique_states =
		UseMultiStateArray(&source_states, &match, &count, source_polygons);

	unsigned total_indices;
	for(i=0,total_indices=0;i<total_polys;i++)
	{
		total_indices += source_polygons[i]->UseIndexArray(&source_indices);
		source_polygons[i]->DetachArrayReferences(&source_indices);
	}
	
	DetachArrayReferences(&source_states);
	DetachArrayReferences(&source_polygons);
	DetachArrayReferences(&source_vertices);
	
	process->TalkAboutAMesh(total_polys, total_vertices, total_indices, unique_states);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	TextureLibrary::GetInfo(
		GetInfoProcess *process
	)
{
	Check_Object(this);
	Check_Object(process);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->InfoCallback(GetInfoProcess::InfoTextureLibraryMode);
	if (!process->continueProcess)
		return;

	//
	//-------------
	// Get the info
	//-------------
	//
	MString name;
	GetName(&name);

	process->TellMyName(&name, GetInfoProcess::InfoTextureLibraryMode);
//	process->TalkAboutATexLibrary(texturePath, ".tga");

	//
	//------------------------------------------------------------------
	// For each texture, get the info
	//------------------------------------------------------------------
	//
	TextureProxy *other_texture = UseFirstTextureProxy();
	while (other_texture)
	{
		Check_Object(other_texture);

		other_texture->GetInfo(process);

		TextureProxy *next = other_texture->UseNextTextureProxyInLibrary();
		other_texture->DetachReference();

		if (process->continueProcess)
			other_texture = next;
		else
		{
			if (other_texture)
				other_texture->DetachReference();
			break;
		}
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	SceneProxy::GetInfo(
		GetInfoProcess *process
	)
{
	Check_Object(this);
	Check_Object(process);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	process->InfoCallback(GetInfoProcess::InfoSceneMode);
	if (!process->continueProcess)
		return;

	process->SetHierarchyLevel();

	//
	//-------------
	// Get the info
	//-------------
	//
	MString name;
	GetName(&name);

	process->TellMyName(&name, GetInfoProcess::InfoSceneMode);

	GetStateLibrary()->GetTextureLibrary()->GetInfo(process);

	//
	//---------------------------------------------------------
	// For each child in the source, copy it to the destination
	//---------------------------------------------------------
	//

	int nrOfChildren = 0;
	process->IncHierarchyLevel();

	ChildProxy *child = UseFirstChildProxy();
	while (child)
	{
		Check_Object(child);

		process->SetHierarchySibling(nrOfChildren++);
		child->GetInfo(process);

		ChildProxy *next = child->UseNextSiblingProxy();
		child->DetachReference();

		if (process->continueProcess)
			child = next;
		else
		{
			if (child)
				child->DetachReference();
			break;
		}
	}
	process->DecHierarchyLevel();
}
