//===========================================================================//
// 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"

namespace Adept {

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

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

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

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

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

		void
			SkipStreamData(MemoryStream *stream);

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

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

	protected:
		AverageOf<T>
			*inputSmoother;

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

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

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

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	template <class T> SmootherOf<T>::~SmootherOf()
	{
		Unregister_Object(inputSmoother);
		delete inputSmoother;
	}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	template <class T> SmootherOf<T>::SmootherOf(
		ClassData *class_data,
		MemoryStream *stream,
		ComponentWeb *owning_web
	):
		ChannelOf<T>(class_data, stream, owning_web)
	{
		//
		//---------------------
		// Hook up to our input
		//---------------------
		//
		ComponentID component_id;
		component_id.scriptResourceID = owning_web->GetScriptResourceID();
		*stream >> component_id.componentNumber;
		Component *component = owning_web->FindComponent(component_id);
		Check_Object(component);
		ChannelOf<T>* channel = Cast_Object(ChannelOf<T>*, component);
		channel->AddDependant(this);

		//
		//------------------------
		// Initialize the smoother
		//------------------------
		//
		size_t size;
		T filler;
		*stream >> size >> filler;
		inputSmoother = new AverageOf<T>(size, filler);
		Register_Object(inputSmoother);
	}

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

		ChannelOf<T>::SkipStreamData(stream);
		stream->AdvancePointer(
			sizeof(componentID.componentNumber) + sizeof(size_t) + sizeof(T)
		);
	}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	template <class T> void
		SmootherOf<T>::ChannelChanged(Channel *channel)
	{
		Check_Object(this);
		Check_Object(channel);
		ChannelOf<T>* input = Cast_Object(ChannelOf<T>*, channel);
		Check_Object(inputSmoother);
		inputSmoother->Add(input->ReadChannel());
		channelOutput = inputSmoother->CalculateAverage();
		NotifyDependantsOfChange();
	}

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

}

