#include "AdeptHeaders.hpp"

#include "VideoHeaders.hpp"

using namespace ElementRenderer;

//
// Class Data Support
//
Component::ClassData*
	SwitchComponent::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	SwitchComponent::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			SwitchComponentClassID,
			"Adept::SwitchComponent",
			BaseClass::DefaultData,
			0,
			NULL
		);
	Register_Object(DefaultData);
}

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
SwitchComponent::SwitchComponent(
	ClassData *shared_data,
	MemoryStream *stream,
	VideoComponentWeb *owning_web
):
	VideoComponent(
		shared_data,
		stream,
		owning_web,
		AllocateSwitch()
	)
{
	//
	//---------------------
	// Hook up to our input
	//---------------------
	//
	ComponentID component_id;
	component_id.scriptResourceID = owning_web->GetScriptResourceID();
	*stream >> component_id.componentNumber;
	Component *component = owning_web->FindComponent(component_id);
	Check_Object(component);
	ChannelOf<int>* channel = Cast_Object(ChannelOf<int>*, component);
	channel->AddDependant(this);

	//
	//---------------------------
	// Get the lOD implementation
	//---------------------------
	//
	SwitchElement *s = GetElement();
	Check_Object(s);

	//
	//-----------------------------
	// Get the number of Switch ranges
	//-----------------------------
	//
	unsigned child_count;
	*stream >> child_count;
	Verify(child_count < 65536);
	s->SetSize(static_cast<WORD>(child_count));

	//
	//--------------------------------------------------------------
	// Spin through the ranges, setting the range for each Switch child
	//--------------------------------------------------------------
	//
	for (WORD i=0; i<child_count; ++i)
	{
		ComponentID component_id;
		component_id.scriptResourceID = owning_web->GetScriptResourceID();
		*stream >> component_id.componentNumber;
		Component *component = owning_web->FindComponent(component_id);
		Check_Object(component);
		VideoComponent *child = Cast_Object(VideoComponent*, component);
		s->AttachIndexedChild(i, child->GetElement());
	}

	//
	//--------------------------------------
	// Set the bounding sphere for this node
	//--------------------------------------
	//
	s->NeedNewBounds();
	unsigned setting = channel->ReadChannel();
	Max_Clamp(setting, child_count);
	s->SetSwitch(static_cast<WORD>(setting));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
SwitchElement*
	SwitchComponent::AllocateSwitch()
{
//	gos_PushCurrentHeap(Heap);
	SwitchElement *s = new SwitchElement;
//	gos_PopCurrentHeap();
	Register_Object(s);
	return s;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
SwitchComponent*
	SwitchComponent::Make(
		MemoryStream *stream,
		VideoComponentWeb *owning_web
	)

{
	SwitchComponent *s =
		new SwitchComponent(DefaultData, stream, owning_web);
	return s;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	SwitchComponent::ChannelChanged(Channel* channel)
{
	Check_Object(this);
	Check_Object(channel);

	//
	//-----------------------------------------------
	// If we got an int based command, set the switch
	//-----------------------------------------------
	//
	if (channel->IsDerivedFrom(ChannelOf<int>::DefaultData))
	{
		ChannelOf<int> *int_channel = Cast_Object(ChannelOf<int>*, channel);
		Verify(static_cast<unsigned>(int_channel->ReadChannel()) < 65536);
		WORD setting = static_cast<WORD>(int_channel->ReadChannel());
		SwitchElement *s = GetElement();
		Check_Object(s);
		s->SetSwitch(setting);
		RendererComponentWeb *web = Cast_Object(RendererComponentWeb *, GetComponentWeb());
		Entity *entity;
		entity = web->GetEntity();
		Check_Object(entity);
		entity->NeedMatrixSync();
	}

	//
	//---------------------------------------
	// Otherwise, let our parent deal with it
	//---------------------------------------
	//
	else
		BaseClass::ChannelChanged(channel);
}

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