//===========================================================================//
// File:	audcmp.hpp                                                          //
// Project: MUNGA           Brick: Audio manager									  //
// Contents: 																					  //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 01/30/95  ECH  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc.                //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#pragma once

#include "Adept.hpp"
#include "Channel.hpp"
#include "ComponentWeb.hpp"

namespace Adept {

	//##########################################################################
	//#######################    AdderChannel    ##########################
	//##########################################################################

	template <class T> class AdderOf:
		public ChannelOf<T>
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructor/Destructor
	//
	public:
		~AdderOf();

		static AdderOf<T>*
			Create(
				MemoryStream *stream,
				ComponentWeb *owning_web
			);

	protected:
		AdderOf(
			ClassData *class_data,
			MemoryStream *stream,
			ComponentWeb *owning_web
		);

		void
			SkipStreamData(MemoryStream *stream);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Class data
	//
	public:
		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Component execution
	//
	public:
		void
			ChannelChanged(Channel *channel);
		void
			Execute();

	protected:
		int
			numberOfInputs;
		ChannelOf<T>
			**inputChannels;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Tool Support
	//
	public:
		static ClassData*
			CreateFactoryRequest(FactoryRequestParameters *parameters);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Test support
	//
	public:
		void
      	TestInstance();
	};

	//
	// Class Data Support
	//
	template <class T> ChannelOf<T>::ClassData*
		AdderOf<T>::DefaultData = NULL;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	template <class T> void
		AdderOf<T>::TerminateClass()
	{
		Unregister_Object(DefaultData);
		delete DefaultData;
		DefaultData = NULL;
	}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	template <class T> AdderOf<T>::~AdderOf()
	{
		Unregister_Pointer(inputChannels);
		delete[] inputChannels;
	}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	template <class T> AdderOf<T>::AdderOf(
		ClassData *class_data,
		MemoryStream *stream,
		ComponentWeb *owning_web
	):
		ChannelOf<T>(class_data, stream, owning_web)
	{
		*stream >> numberOfInputs;
		Verify(static_cast<unsigned>(numberOfInputs) > 0);
		inputChannels = new ChannelOf<T>*[numberOfInputs];
		Register_Pointer(inputChannels);
		Check_Object(owning_web);
		ComponentID component_id;
		component_id.scriptResourceID = owning_web->GetScriptResourceID();
		for (int i=0; i<numberOfInputs; ++i)
		{
			*stream >> component_id.componentNumber;
			Component *component = owning_web->FindComponent(component_id);
			Check_Object(component);
			ChannelOf<T>* channel = Cast_Object(ChannelOf<T>*, component);
			inputChannels[i] = channel;
			channel->AddDependant(this);
		}
	}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	template <class T> void
		AdderOf<T>::SkipStreamData(MemoryStream *stream)
	{
		Check_Object(this);
		Check_Object(stream);

		int inputs;
		*stream >> inputs;
		Verify(inputs == numberOfInputs);
		stream->AdvancePointer(inputs*sizeof(componentID.componentNumber));
	}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	template <class T> AdderOf<T>*
		AdderOf<T>::Create(
			MemoryStream *stream,
			ComponentWeb *owning_web
		)
	{
		Check_Object(stream);
		Check_Object(owning_web);
		Component *component = DoesComponentExist(stream, owning_web);
		AdderOf<T> *adder;
		if (component)
		{
			adder = Cast_Object(AdderOf<T>*, component);
			adder->SkipStreamData(stream);
		}
		else
		{
			adder = new AdderOf<T>(DefaultData, stream, owning_web);
			Register_Object(adder);
		}
		return adder;
	}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	template <class T> void
		AdderOf<T>::ChannelChanged(Channel *channel)
	{
		Check_Object(this);
		Check_Object(channel);
		ComponentWeb *web = GetComponentWeb();
		Check_Object(web);
		web->AddTemporaryWatcher(this);
	}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	template <class T> void
		AdderOf<T>::TestInstance()
	{
		Verify(IsDerivedFrom(DefaultData));
	}

}

