//===========================================================================//
// 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 "Tool.hpp"

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	ComponentWeb::CreateComponentStream(
		ResourceID					*stream_resource,
		NotationFile 				*model_file,
		NotationFile				*component_file,
		FactoryRequestCreator		component_builder,
		Component::CommandEncoder	command_encoder
	)
{
	Check_Object(stream_resource);
	Check_Object(model_file);
	Check_Object(component_file);

	Check_Object(ResourceManager::Instance);

	//
	//--------------------------
	// handle an empty .sub file
	//--------------------------
	//
	bool result = true;
	NotationFile::PageIterator *pages = component_file->MakePageIterator();
	Check_Object(pages);
	int page_count = pages->GetSize();
	if (!page_count)
	{
		STOP(("%s is an empty file!", component_file->GetFileName()));
		result = false;
	}

	//
	//----------------------------------------------------------------
	// Now start building the stream by first putting in the number of 
	// components
	//----------------------------------------------------------------
	//
	Channel::FactoryRequestParameters parameters;

	DynamicMemoryStream component_stream;
	component_stream << page_count;
	parameters.m_stream = &component_stream;

	parameters.m_index = 0;
	parameters.m_commandEncoder = command_encoder;
	parameters.m_components = new DynamicArrayOf<ComponentDescriptor>(page_count);
	Check_Object(parameters.m_components);

	//
	//--------------------------------
	// Get the list of component names
	//--------------------------------
	//
	while ((parameters.m_page = pages->ReadAndNext()) != NULL)
	{
		Check_Object(parameters.m_page);

		//
		//------------------------------
		// Get the type of the component
		//------------------------------
		//
		const char* component_type;
		parameters.m_page->GetEntry("Type", &component_type, true);

		//
		//------------------------------------------------------------
		// Store where the stream currently is, and set a dummy length
		//------------------------------------------------------------
		//
		int record_start = component_stream.GetIndex();
		component_stream << 0;

		//
		//---------------------------
		// Call the component creator
		//---------------------------
		//
		Component::ClassData *derivation =
			(*component_builder)(component_type,&parameters);
		if (!derivation)
			result = false;
		else
		{
			int end = component_stream.GetIndex();
			component_stream.SetPointer(record_start);
			component_stream << (end - record_start);
			component_stream.SetPointer(end);
			Check_Object(derivation);

			ComponentDescriptor *descriptor = &(*parameters.m_components)[parameters.m_index++];
			Check_Object(descriptor);
			descriptor->m_name = parameters.m_page->GetName();
			descriptor->m_classData = derivation;
		}
	}
	Verify(parameters.m_index == page_count);

	//
	//---------------------------------------
	// Store the damage zone in the resources
	//---------------------------------------
	//
	if (result)
	{
		Resource new_res(component_file->GetFileName());
		new_res.Save(&component_stream, component_file->GetFileDependencies());
		STOP(("Not updated"));
		*stream_resource = new_res.GetResourceID();
	}

	//
	//-------------------------
	// Release allocated memory
	//-------------------------
	//
	Check_Object(parameters.m_components);
	delete parameters.m_components;
	Check_Object(pages);
	delete pages;

	return result;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	EntityComponentWeb::CreateComponentStream(
		ResourceID					*stream_resource,
		Entity::ClassData			*class_data,
		NotationFile 				*model_file,
		NotationFile				*component_file,
		FactoryRequestCreator		component_builder,
		Component::CommandEncoder	command_encoder
	)
{
	Check_Object(stream_resource);
	Check_Object(model_file);
	Check_Object(component_file);

	Check_Object(ResourceManager::Instance);

	//
	//--------------------------
	// handle an empty .sub file
	//--------------------------
	//
	bool result = true;
	NotationFile::PageIterator *pages = component_file->MakePageIterator();
	Check_Object(pages);
	int page_count = pages->GetSize();
	if (!page_count)
	{
		STOP(("%s is an empty file!", component_file->GetFileName()));
		result = false;
	}

	//
	//----------------------------------------------------------------
	// Now start building the stream by first putting in the number of 
	// components
	//----------------------------------------------------------------
	//
	Channel::FactoryRequestParameters parameters;

	DynamicMemoryStream component_stream;
	component_stream << page_count;
	parameters.m_stream = &component_stream;

	parameters.m_index = 0;
	parameters.m_commandEncoder = command_encoder;
	parameters.m_components = new DynamicArrayOf<ComponentDescriptor>(page_count);
	Check_Object(parameters.m_components);

	//
	//--------------------------------
	// Get the list of component names
	//--------------------------------
	//
	while ((parameters.m_page = pages->ReadAndNext()) != NULL)
	{
		Check_Object(parameters.m_page);

		//
		//------------------------------
		// Get the type of the component
		//------------------------------
		//
		const char* component_type;
		parameters.m_page->GetEntry("Type", &component_type, true);

		//
		//------------------------------------------------------------
		// Store where the stream currently is, and set a dummy length
		//------------------------------------------------------------
		//
		int record_start = component_stream.GetIndex();
		component_stream << 0;

		Component::ClassData *derivation =
			(*component_builder)(component_type,&parameters, class_data);

		if (!derivation)
			result = false;
		else
		{
			int end = component_stream.GetIndex();
			component_stream.SetPointer(record_start);
			component_stream << (end - record_start);
			component_stream.SetPointer(end);
			Check_Object(derivation);

			ComponentDescriptor *descriptor = &(*parameters.m_components)[parameters.m_index++];
			Check_Object(descriptor);
			descriptor->m_name = parameters.m_page->GetName();
			descriptor->m_classData = derivation;
		}
	}

	//
	//---------------------------------------
	// Store the damage zone in the resources
	//---------------------------------------
	//
	if (result)
	{
		Resource new_res(component_file->GetFileName());
		new_res.Save(&component_stream, component_file->GetFileDependencies());
		STOP(("Not updated"));
		*stream_resource = new_res.GetResourceID();
	}

	//
	//-------------------------
	// Release allocated memory
	//-------------------------
	//
	Check_Object(parameters.m_components);
	delete parameters.m_components;
	Check_Object(pages);
	delete pages;

	return result;
}
