#include "AdeptHeaders.hpp"

#include "LightComponent.hpp"
#include "VideoHeaders.hpp"
#include "LightManager.hpp"
#include "Attribute.hpp"
#include <ElementRenderer\LightElement.hpp>
#include <MLR\MLRLight.hpp>

//############################################################################
//###############################  LightComponent  ################################
//############################################################################

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

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

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
LightComponent::LightComponent(
	ClassData *class_data,
	MemoryStream *stream,
	VideoComponentWeb *owning_web
):
	VideoComponent(
		class_data,
		stream,
		owning_web,
		AllocateLight()
	)
{
	Check_Object(this);

	//
	//---------------------
	// Get the gosFX number
	//---------------------
	//
	gos_PushCurrentHeap(MidLevelRenderer::LightsHeap);
	MidLevelRenderer::MLRLight *mlight =
		MidLevelRenderer::MLRLight::Make(
			stream,
			MidLevelRenderer::ReadMLRVersion(stream)
		);
	gos_PopCurrentHeap();
	Check_Object(mlight);
	gosFX::Light *glight =
		ElementRenderer::LightElementManager::Instance->MakeLight(mlight);
	ElementRenderer::LightElement *elight = GetElement();
	Check_Object(elight);
	elight->AdoptLight(glight);

	int attribute_id;
	*stream >> attribute_id;
	owningEntity = owning_web->GetEntity();
	Check_Object(owningEntity);
	Verify(attribute_id != -1);
	intensityAttribute = owningEntity->GetAttributeEntry(attribute_id);
	Check_Object(intensityAttribute);
	Verify(intensityAttribute->attributeType == ScalarClassID);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Element*
	LightComponent::AllocateLight()
{
	//
	//---------------------
	// Get the gosFX number
	//---------------------
	//
	gos_PushCurrentHeap(ElementRenderer::LightElement::s_Heap);
	ElementRenderer::LightElement *light =
		new ElementRenderer::LightElement;
	gos_PopCurrentHeap();
	Check_Object(light);
	return light;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	LightComponent::SkipStreamData(MemoryStream *stream)
{
	Check_Object(this);
	Check_Object(stream);

	BaseClass::SkipStreamData(stream);

	gos_PushCurrentHeap(MidLevelRenderer::LightsHeap);
	MidLevelRenderer::MLRLight *light =
		MidLevelRenderer::MLRLight::Make(
			stream,
			MidLevelRenderer::ReadMLRVersion(stream)
		);
	gos_PopCurrentHeap();
	delete light;

	int attribute_id;
	*stream >> attribute_id;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
LightComponent*
	LightComponent::Create(
		MemoryStream *stream,
		VideoComponentWeb *owning_web
	)
{
	Check_Object(stream);
	Check_Object(owning_web);
	Component *component = DoesComponentExist(stream, owning_web);
	LightComponent *object;
	if (component)
	{
		object = static_cast<LightComponent*>(component);
		Check_Object(object);
		object->SkipStreamData(stream);
	}
	else
	{
		object = new LightComponent(DefaultData, stream, owning_web);
		Register_Object(object);
	}
	return object;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	LightComponent::Execute()
{
	Check_Object(this);

	if(intensityAttribute)
	{
		ElementRenderer::LightElement *light = GetElement();
		Check_Object(light);
		gosFX::Light *gos_light = light->GetLight();
		Check_Object(gos_light);
		Scalar value;
		intensityAttribute->GetValue(owningEntity, &value);
		light->m_lightInfo.m_intensity = value;
		gos_light->ChangeLight(&light->m_lightInfo);
	}
}

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

	//
	//--------------------------
	// Get the new channel value
	//--------------------------
	//
	Check_Object(channel);
	ChannelOf<Scalar>* input = Cast_Object(ChannelOf<Scalar>*, channel);
	Scalar value = input->ReadChannel();

	//
	//--------------------------------
	// Use it to set the dimmer switch
	//--------------------------------
	//
	ElementRenderer::LightElement *light = GetElement();
	Check_Object(light);
	gosFX::Light *gos_light = light->GetLight();
	Check_Object(gos_light);
	light->m_lightInfo.m_intensity = value;
	gos_light->ChangeLight(&light->m_lightInfo);
}

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