#include "AdeptHeaders.hpp"

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Channel::ClassData*
	Channel::CreateFactoryRequest(FactoryRequestParameters *parameters)
{
	Check_Object(parameters);

	//
	//-------------------------------------------------------------------------
	// Allocate enough room for what we need to write out, then call our parent
	//-------------------------------------------------------------------------
	//
	MemoryStream *component_stream = parameters->m_stream;
	Check_Object(component_stream);
	component_stream->AllocateBytes(sizeof(Channel));
	bool result = BaseClass::CreateFactoryRequest(parameters) != NULL;
	Page *page = parameters->m_page;
	Check_Object(page);

	//
	//------------------------------------------------------
	// Decode the channel command and stick it in the stream
	//------------------------------------------------------
	//
	const char* command;
	int command_id = 0;
	if (page->GetEntry("Command", &command))
	{
		command_id = (*parameters->m_commandEncoder)(command);
		if (command_id == -1)
		{
			PAUSE((
				"%s: {[%s]Command=%s}: Unknown command!",
				page->GetNotationFile()->GetFileName(),
				page->GetName(),
				command
			));
			result = false;
		}
	}
	*component_stream << command_id;

	//
	//---------------------------------------------
	// Find all the places the command should go to
	//---------------------------------------------
	//
	if (!ReadOutputsFromPage(parameters))
		result = false;

	Check_Object(DefaultData);
	return (result) ? DefaultData : NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	Channel::ReadOutputsFromPage(FactoryRequestParameters *parameters)
{
	Check_Object(parameters);

	Page *page = parameters->m_page;
	Check_Object(page);
	MemoryStream *component_stream = parameters->m_stream;
	Check_Object(component_stream);

	bool result = true;

	//
	//---------------------------------------------
	// Find all the places the command should go to
	//---------------------------------------------
	//
	DynamicArrayOf<ComponentDescriptor> *list = parameters->m_components;
	Check_Object(list);
	ChainOf<Note*>* output_entries = page->MakeNoteChain("Output");
	Check_Object(output_entries);
	Page::NoteIterator outputs(output_entries);
	int output_count = outputs.GetSize();
	*component_stream << output_count;
	Note *output;
	while ((output = outputs.ReadAndNext()) != NULL)
	{
		Check_Object(output);
		const char* output_name = NULL;
		output->GetEntry(&output_name);
		Check_Pointer(output_name);
		int output_id = ComponentDescriptor::FindName(list, parameters->m_index, output_name);
		if (output_id == -1)
		{
			PAUSE((
				"%s: {[%s]Output=%s}: Unknown component name!",
				page->GetNotationFile()->GetFileName(),
				page->GetName(),
				output_name
			));
			result = false;
		}
		else
		{
			*component_stream << output_id;
		}
	}
	Check_Object(output_entries);
	delete output_entries;

	return result;
}

