//===========================================================================//
// File:	cmpnnt.cc                                                           //
// Project: MUNGA           Brick: Entity												  //
// Contents: 																					  //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 12/14/94  ECH  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc.                //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#include "AdeptHeaders.hpp"
#include "Renderer.hpp"

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	ComponentID::operator==(const ComponentID& component) const
{
	return
		component.scriptResourceID == scriptResourceID
		 && component.componentNumber == componentNumber;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	ComponentID::operator!=(const ComponentID& component) const
{
	return
		component.scriptResourceID != scriptResourceID
		 || component.componentNumber != componentNumber;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	ComponentID::operator>(const ComponentID& component) const
{
	return
		(component.scriptResourceID == scriptResourceID) ?
			(componentNumber > component.componentNumber) :
			(scriptResourceID > component.scriptResourceID);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Component ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//
// Shared Data Support
//
Component::ClassData*
	Component::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Component::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			ComponentClassID,
			"Adept::Component",
			Receiver::DefaultData,
			0,
			NULL
		);
	Register_Object(DefaultData);
}

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Component::Component(ClassData *class_data):
	Receiver(class_data)
{
	componentWeb = NULL;
	componentFlags = 0;
	componentID.scriptResourceID = ResourceID::Null;
	componentID.componentNumber = 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Component::~Component()
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Component::Component(
	ClassData *class_data,
	MemoryStream *stream,
	ComponentWeb *owning_web
):
	Receiver(class_data)
{
	Check_Object(stream);
	Check_Object(owning_web);
	componentWeb = owning_web;

	//
	//----------------------------------------
	// Read the flags and set the component ID
	//----------------------------------------
	//
	componentID.scriptResourceID = owning_web->GetScriptResourceID();
	*stream >> componentID.componentNumber;
	*stream >> componentFlags;
}

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

	//
	//----------------------------------------
	// Read the flags and set the component ID
	//----------------------------------------
	//
	int id;
	*stream >> id;
	Verify(id == componentID.componentNumber);
	int flags;
	*stream >> flags;
	Verify(flags == componentFlags);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
unsigned
	Component::GetStreamSize(MemoryStream *stream)
{
	return 2*sizeof(int);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Component*
	Component::DoesComponentExist(
		MemoryStream *stream,
		ComponentWeb *web
	)
{
	Check_Object(stream);
	Check_Object(web);

	//
	//------------------------------------------------------------------------
	// Read the component number and flags from the stream, then rewind it for
	// the constructor
	//------------------------------------------------------------------------
	//
	ComponentID id;
	id.scriptResourceID = web->GetScriptResourceID();
	*stream >> id.componentNumber;
	int flags;
	*stream >> flags;
	stream->RewindPointer(sizeof(id.componentNumber) + sizeof(flags));

	//
	//-----------------------------------------------
	// Only renderers currently share data components
	//-----------------------------------------------
	//
	if (!(flags & SharedFlag))
	{
		return NULL;
	}
	RendererComponentWeb *renderer_web =
		Cast_Object(RendererComponentWeb*, web);
	Renderer* renderer = renderer_web->GetRenderer();
	Check_Object(renderer);
	return renderer->FindSharedComponent(id);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Component::ReadInputsFromStream(
		MemoryStream *stream,
		ComponentWeb *owning_web
	)
{
	Check_Object(this);
	Check_Object(stream);
	Check_Object(owning_web);
	//
	//----------------------
	// Connect to the inputs
	//----------------------
	//
	unsigned i, number_of_entries;
	*stream >> number_of_entries;
	ComponentID component_id;
	component_id.scriptResourceID = owning_web->GetScriptResourceID();
	for (i = 0; i < number_of_entries; i++)
	{
		*stream >> component_id.componentNumber;
		Component *component = owning_web->FindComponent(component_id);
		Check_Object(component);
		Channel *channel = Cast_Object(Channel*, component);
		channel->AddDependant(this);
	}	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Component::Execute()
{
	Check_Object(this);
}

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

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