#include "ProxyHeaders.hpp"

//
//############################################################################
//###########################    StateProxy    ############################
//############################################################################
//

StateProxy::ClassData*
	StateProxy::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	StateProxy::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			StateProxyClassID,
			"StateProxy",
			GenericProxy::DefaultData
		);
	Register_Object(DefaultData);
}

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
StateProxy::StateProxy(
	ClassData *class_data,
	StateLibrary *library
):
	GenericProxy(class_data),
	libraryProxy(library)
{
	Check_Pointer(this);
	Check_Object(libraryProxy);
	libraryProxy->AttachStateProxy(this);
	Check_Object(this);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
StateProxy::~StateProxy()
{
	Check_Object(this);
	Check_Object(libraryProxy);
	libraryProxy->DetachReference();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	StateProxy::IsEqualTo(StateProxy *state)
{
	Check_Object(this);
	Check_Object(state);

	//
	//-------------------------------
	// We are always equal to ourself
	//-------------------------------
	//
	if (this == state)
		return true;

	//
	//-------------------------------------
	// Compare the specular color and value
	//-------------------------------------
	//
	RGBColor color, other_color;
	bool them = state->GetSpecularColor(&other_color);
	bool us = GetSpecularColor(&color);
	if (them != us)
		return false;
	if (them && us)
	{
		if (
			!Close_Enough(color, other_color)
			 ||
				!Close_Enough(
					GetSpecularShininess(),
					state->GetSpecularShininess()
				)
		)
			return false;
	}

	bool themOnOff, usOnOff;

	//
	//-----------------------------
	// Compare the alpha proxies
	//-----------------------------
	//
	AlphaMode themAlpha, usAlpha;

	themOnOff = state->GetAlpha(&themAlpha);
	usOnOff = GetAlpha(&usAlpha);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themAlpha != usAlpha) )
	{
		return false;
	}

	themOnOff = state->GetAlphaChildPermission();
	usOnOff = GetAlphaChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//-----------------------------
	// Compare the Filter proxies
	//-----------------------------
	//
	FilterMode themFilter, usFilter;

	themOnOff = state->GetFilter(&themFilter);
	usOnOff = GetFilter(&usFilter);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themFilter != usFilter) )
	{
		return false;
	}

	themOnOff = state->GetFilterChildPermission();
	usOnOff = GetFilterChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//-----------------------------
	// Compare the Fog proxies
	//-----------------------------
	//
	FogMode themFog, usFog;

	themOnOff = state->GetFog(&themFog);
	usOnOff = GetFog(&usFog);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themFog != usFog) )
	{
		return false;
	}

	themOnOff = state->GetFogChildPermission();
	usOnOff = GetFogChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//-----------------------------
	// Compare the Dither proxies
	//-----------------------------
	//
	bool themDither, usDither;

	themOnOff = state->GetDither(&themDither);
	usOnOff = GetDither(&usDither);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themDither != usDither) )
	{
		return false;
	}

	themOnOff = state->GetDitherChildPermission();
	usOnOff = GetDitherChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//-----------------------------
	// Compare the Specular proxies
	//-----------------------------
	//
	bool themSpecular, usSpecular;

	themOnOff = state->GetSpecular(&themSpecular);
	usOnOff = GetSpecular(&usSpecular);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themSpecular != usSpecular) )
	{
		return false;
	}

	themOnOff = state->GetSpecularChildPermission();
	usOnOff = GetSpecularChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//-----------------------------
	// Compare the TextureCorrection proxies
	//-----------------------------
	//
	bool themTextureCorrection, usTextureCorrection;

	themOnOff = state->GetTextureCorrection(&themTextureCorrection);
	usOnOff = GetTextureCorrection(&usTextureCorrection);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themTextureCorrection != usTextureCorrection) )
	{
		return false;
	}

	themOnOff = state->GetTextureCorrectionChildPermission();
	usOnOff = GetTextureCorrectionChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//-----------------------------
	// Compare the TextureWrap proxies
	//-----------------------------
	//
	TextureWrapMode themTextureWrap, usTextureWrap;

	themOnOff = state->GetTextureWrap(&themTextureWrap);
	usOnOff = GetTextureWrap(&usTextureWrap);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themTextureWrap != usTextureWrap) )
	{
		return false;
	}

	themOnOff = state->GetTextureWrapChildPermission();
	usOnOff = GetTextureWrapChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//-----------------------------
	// Compare the WireFrame proxies
	//-----------------------------
	//
	WireFrameMode themWireFrame, usWireFrame;

	themOnOff = state->GetWireFrame(&themWireFrame);
	usOnOff = GetWireFrame(&usWireFrame);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themWireFrame != usWireFrame) )
	{
		return false;
	}

	themOnOff = state->GetWireFrameChildPermission();
	usOnOff = GetWireFrameChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//-----------------------------
	// Compare the ZBufferCompare proxies
	//-----------------------------
	//
	bool themZBufferCompare, usZBufferCompare;

	themOnOff = state->GetZBufferCompare(&themZBufferCompare);
	usOnOff = GetZBufferCompare(&usZBufferCompare);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themZBufferCompare != usZBufferCompare) )
	{
		return false;
	}

	themOnOff = state->GetZBufferCompareChildPermission();
	usOnOff = GetZBufferCompareChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//-----------------------------
	// Write the ZBufferWrite proxies
	//-----------------------------
	//
	bool themZBufferWrite, usZBufferWrite;

	themOnOff = state->GetZBufferWrite(&themZBufferWrite);
	usOnOff = GetZBufferWrite(&usZBufferWrite);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themZBufferWrite != usZBufferWrite) )
	{
		return false;
	}

	themOnOff = state->GetZBufferWriteChildPermission();
	usOnOff = GetZBufferWriteChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//-----------------------------
	// Write the FlatColoring proxies
	//-----------------------------
	//
	bool themFlatColoring, usFlatColoring;

	themOnOff = state->GetFlatColoring(&themFlatColoring);
	usOnOff = GetFlatColoring(&usFlatColoring);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themFlatColoring != usFlatColoring) )
	{
		return false;
	}

	themOnOff = state->GetFlatColoringChildPermission();
	usOnOff = GetFlatColoringChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//-----------------------------
	// Compare the two-sided proxies
	//-----------------------------
	//
	bool themTSoverride, usTSoverride;

	themOnOff = state->GetMatTwoSided(&themTSoverride);
	usOnOff = GetMatTwoSided(&usTSoverride);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themTSoverride != usTSoverride) )
	{
		return false;
	}

	themOnOff = state->GetMatTwoSidedChildPermission();
	usOnOff = GetMatTwoSidedChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//-----------------------------
	// Compare the backface proxies
	//-----------------------------
	//
	bool themBFoverride, usBFoverride;

	themOnOff = state->GetBackface(&themBFoverride);
	usOnOff = GetBackface(&usBFoverride);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themBFoverride != usBFoverride) )
	{
		return false;
	}

	themOnOff = state->GetBackfaceChildPermission();
	usOnOff = GetBackfaceChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//-----------------------------
	// Write the Priority proxies
	//-----------------------------
	//
	int themPriority, usPriority;

	themOnOff = state->GetPriority(&themPriority);
	usOnOff = GetPriority(&usPriority);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themPriority != usPriority) )
	{
		return false;
	}

	themOnOff = state->GetPriorityChildPermission();
	usOnOff = GetPriorityChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//-----------------------------
	// Write the Lighting proxies
	//-----------------------------
	//
	int themLighting, usLighting;

	themOnOff = state->GetLighting(&themLighting);
	usOnOff = GetLighting(&usLighting);

	if(themOnOff != usOnOff)
	{
		return false;
	}
	if(usOnOff && (themLighting != usLighting) )
	{
		return false;
	}

	themOnOff = state->GetLightingChildPermission();
	usOnOff = GetLightingChildPermission();

	if(themOnOff != usOnOff)
	{
		return false;
	}

	//
	//----------------------------
	// Compare the texture proxies
	//----------------------------
	//
	TextureProxy *texture = state->UseTextureProxy();
	TextureProxy *our_texture = UseTextureProxy();
	if (!texture && !our_texture)
		return true;
	bool result = false;
	if (texture && our_texture)
		result = texture->IsEqualTo(our_texture);
	if (our_texture)
		our_texture->DetachReference();
	if (texture)
		texture->DetachReference();
	return result;
}

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

//
//############################################################################
//######################    StateLibrary    ##########################
//############################################################################
//

StateLibrary::ClassData*
	StateLibrary::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	StateLibrary::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			StateLibraryClassID,
			"StateLibrary",
			GenericProxy::DefaultData
		);
	Register_Object(DefaultData);
}

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
StateLibrary::StateLibrary(
	ClassData *class_data,
	SceneProxy *scene
):
	GenericProxy(class_data),
	sceneProxy(scene),
	activeStateProxies(NULL)
{
	Check_Object(this);
	textureLibrary = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
StateLibrary::~StateLibrary()
{
	Check_Object(this);
	Verify(activeStateProxies.IsEmpty());
	Verify(!textureLibrary);
}

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