#include "ElementProxyHeaders.hpp"

//----------------------------------------------------------------------------
//
bool
	OptimizeSyncProcess::OptimizeSync(ChildProxy *child)
{
	Check_Object(this);
	Check_Object(child);

	if (child->IsDerivedFrom(ElementGroupProxy::DefaultData))
	{
		ElementGroupProxy *group = Cast_Object(ElementGroupProxy*, child);
		return OptimizeSync(group);
	}
	else if (child->IsDerivedFrom(ElementPolygonMeshProxy::DefaultData))
	{
		ElementPolygonMeshProxy *mesh = Cast_Object(ElementPolygonMeshProxy*, child);
		return OptimizeSync(mesh);
	}
	else if (child->IsDerivedFrom(ElementListProxy::DefaultData))
	{
		return true;
	}
	STOP(("Shouldn't get here..."));
	OptimizeCallback(child);
	return false;
}

//----------------------------------------------------------------------------
//
bool
	OptimizeSyncProcess::OptimizeSync(ElementGroupProxy* group)
{
	Check_Object(this);
	Check_Object(group);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	OptimizeCallback(group);
	if (!continueProcess)
		return true;

	//
	//--------------------
	// Kill the group name
	//--------------------
	//
	group->SetName(NULL);

	//
	//-----------------------------
	// Run optimize on the children
	//-----------------------------
	//
	unsigned child_count = group->GetChildCount();
	ChildProxy *child = group->UseFirstChildProxy();
	for (unsigned i=0; i<child_count; ++i)
	{
		Check_Object(child);
		ChildProxy *next = child->UseNextSiblingProxy();
		if (OptimizeSync(child))
			child->DetachReference();
		child = next;
		if (!continueProcess)
			break;
	}

	//
	//-------------------------------------------
	// Make sure to discard any remaining proxies
	//-------------------------------------------
	//
	if (child)
		child->DetachReference();

	//
	//-------------------------------------------------------------------------
	// If this node is under a set, or does not have an interest zone under it,
	// go ahead and set it to OnDemand sync
	//-------------------------------------------------------------------------
	//
	Sphere sphere;
	if (group->GroupProxy::GetBoundingSphere(&sphere))
		group->SetBoundingSphere(sphere);

	//
	//-----------------------------------------------------------------------
	// Move the group children to a list and hook it up to the same parent as
	// the group
	//-----------------------------------------------------------------------
	//
	GroupElement *element = group->GetProxiedGroup();
	Check_Object(element);
	ListElement *list = new ListElement(element);
	Register_Object(list);
	Element *parent = element->GetParentElement();
	if (parent)
	{
		Check_Object(parent);
		parent->AttachChild(list);
	}
	list->Sync();

	//
	//---------------------
	// Now delete the group
	//---------------------
	//
	group->Destroy();
	return false;
}

//----------------------------------------------------------------------------
//
bool
	OptimizeSyncProcess::OptimizeSync(ElementPolygonMeshProxy* mesh)
{
	Check_Object(this);
	Check_Object(mesh);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	OptimizeCallback(mesh);
	if (!continueProcess)
		return true;

	//
	//--------------------------------------
	// We don't need names on polygon meshes
	//--------------------------------------
	//
	mesh->SetName(NULL);

	//
	//----------------------------
	// Compute the bounding sphere
	//----------------------------
	//
	Sphere sphere;
	if (mesh->PolygonMeshProxy::GetBoundingSphere(&sphere))
		mesh->SetBoundingSphere(sphere);
	return true;
}

//----------------------------------------------------------------------------
//
void
	OptimizeSyncProcess::OptimizeSync(ElementSceneProxy* scene)
{
	Check_Object(this);
	Check_Object(scene);

	//
	//---------------------------------------
	// Make sure that the process says its OK
	//---------------------------------------
	//
	OptimizeCallback(scene);
	if (!continueProcess)
		return;

	//
	//--------------
	// Kill the name
	//--------------
	//
	scene->SetName(NULL);

	//
	//-----------------------------
	// Run optimize on the children
	//-----------------------------
	//
	ChildProxy *child = scene->UseFirstChildProxy();
	while (child)
	{
		Check_Object(child);
		ChildProxy *next = child->UseNextSiblingProxy();
		if (OptimizeSync(child))
			child->DetachReference();
		child = next;
		if (!continueProcess)
			break;
	}

	//
	//-------------------------------------------
	// Make sure to discard any remaining proxies
	//-------------------------------------------
	//
	if (child)
		child->DetachReference();

	//
	//------------------------------------
	// Set the sync mode of the scene root
	//------------------------------------
	//
	Sphere sphere;
	if (scene->SceneProxy::GetBoundingSphere(&sphere))
		scene->SetBoundingSphere(sphere);
}
