#include "ObjProNet/dfnode.h"

#include "ObjProUsr/mux.h"
#include "ObjProGen/outtok.h"
#include "ObjProGui/intfc.h"
#include "ObjProGui/remmen.h"
#include "ObjProGui/user.h"
#include "ObjProGui/dynmnu.h"
#include "ObjProArith/typout.h"
#include "ObjProGui/array.h"
#include "ObjProGui/interinit.h"
#include "ObjProGen/stattyp.h"
#include "ObjProGen/gcd.h"
#include "ObjProComGui/cgidbg.h"
static EntityList * MuxNodeList = 0 ;
static InteractiveEntity * IntEntMux ;
void MuxNodesInit();
Mux::Mux (const char * Name, int16 Channels, int32 InputSampleSize, 
		int32 OutputSampleSize, int16 MinimumChunk):
	ProcessNode(Name, Channels, 1, InputSampleSize, 0, 
	OutputSampleSize * MinimumChunk, MinimumChunk * Channels * InputSampleSize, 0, 0, OutputSampleSize, 
	0, TimingTypeLinear, 
	(ArithType::ArithCapabilities)ArithType::ArithTypeUndefined, (ArithType::ArithCapabilities)ArithType::ArithTypeUndefined)
,
	Channels_1(Channels),
	InputSampleSize_2(InputSampleSize),
	OutputSampleSize_3(OutputSampleSize),
	MinimumChunk_4(MinimumChunk)
{
	if (!MuxNodeList) MuxNodesInit() ;
	MuxNodeList->Append(MakeDeclaredEntity(this, IntEntMux)) ;
	InitArithType(TheArithType);
	NewMenuItem("Mux",GetName());
} // end constructor

Mux::~Mux()
{
	TheMenuServer->DeleteMenuItem("Mux",GetName());
	MuxNodeList->Delete(GetName()) ;
} // end destructor

int Mux::CheckSafeDelete()
{
	int Safe_Check_Return = DfNode::CheckSafeDelete();
	if (!Safe_Check_Return) return 0;
	return 1;
} // end check safe delete

Mux * MuxDef;

ErrCode Mux::DoNode(int32 k)
{
#line 60 "../mux.usr"
 
	int32 Limit = k * GetMinimumChunk() ;
	// TheLog << "Limit = " << Limit << "\n" ;
	for (int32 i = 0 ; i < Limit ; i++ )
		for (int16 Channel= 0 ; Channel < GetChannels() ; Channel++) 
			for (int32 l = 0 ; l < GetInputSampleSize(); l++) {
				MachWord Data = ReadWord(Channel);
				WriteWord(Data, 0) ;
	}
	return OK ;
#line 65 "../mux.cxx"
} // end kernel code

static UserEntity * MakeMux(OutTokens& Out, EntityReq Request,
	InteractiveEntity& IntNode,
	ArithType::ArithCapabilities arith = (ArithType::ArithCapabilities) TheArithType) ;
int Mux::CppList(OutTokens& Out, CppListCmds Cmd)
{
	return IntEntMux->CppList(Out,Cmd,this);
}

void Mux::Describe(OutTokens& Out, ListEntity Option)
{
	switch(Option) {
case ListSingleEntity:
		Out.NewLine();
		MakeMux(Out,EntityReqDescribeFull,*IntEntMux, (ArithType::ArithCapabilities) TheArithType);
		Out.NewLine();
		Out.NextQuoteOut("Mux");
		Out.NextFillOut("combines");
		Out.NextQuoteOut("Channels");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetChannels()));
		Out.NextFillOut(")");
		Out.NextFillOut("input channels into");
		Out.NextFillOut("a single output channel.");
		Out.NextFillOut("For each input channel it is assumed that a");
		Out.NextFillOut("single sample is made up of");
		Out.NextQuoteOut("InputSampleSize");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetInputSampleSize()));
		Out.NextFillOut(")");
		Out.NextFillOut("words.");
		Out.NextFillOut("The number of words in an output channel sample is");
		Out.NextQuoteOut("OutputSampleSize");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetOutputSampleSize()));
		Out.NextFillOut(")");
		Out.NextFillOutConcat(".");
		Out.NextQuoteOut("MinimumChunk");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetMinimumChunk()));
		Out.NextFillOut(")");
		Out.NextFillOut("can be set to a minimum number of input");
		Out.NextFillOut("samples to be processed. This allows for greater");
		Out.NextFillOut("efficiency but limits the degree to which");
		Out.NextFillOut("data can be flushed.");
		Out.NewLine();
		break;
case ListEntityMembers:
		Out.NextOut(GetName());
		break;
case ListGlobalClasses:
case ListEntityClasses:
		break ;
case ListSetParameterValues:
		IntEntMux->GetOneParameter("Channels")->
			IntP->CurrentValue = Channels_1;
		IntEntMux->GetOneParameter("InputSampleSize")->
			IntP->CurrentValue = InputSampleSize_2;
		IntEntMux->GetOneParameter("OutputSampleSize")->
			IntP->CurrentValue = OutputSampleSize_3;
		IntEntMux->GetOneParameter("MinimumChunk")->
			IntP->CurrentValue = MinimumChunk_4;
		break;
	}
} // end  list entity switch

void MuxNodesInit()
{
	if (MuxNodeList)  return ;

	static StringParam MuxNameParam =
		{"Mux", MakeNewEntityName, 0, LegalEntityName};
	static IntParam MuxChannelsParam = {
		 2, 0,  0,  2, 0, 32767};
	static IntParam MuxInputSampleSizeParam = {
		 1, 0,  0,  1, 0, 2.14748e+09};
	static IntParam MuxOutputSampleSizeParam = {
		 2, 0,  0,  1, 0, 2.14748e+09};
	static IntParam MuxMinimumChunkParam = {
		 1, 0,  0,  1, 0, 32767};

	static OneParameter MuxParArray[] = {
		{"Name", 0, "node name", 0, 0, &MuxNameParam},
		{"Channels", 0, 
			"number of input channels",
			&MuxChannelsParam},
		{"InputSampleSize", 0, 
			"number of consecutive words in one sample",
			&MuxInputSampleSizeParam},
		{"OutputSampleSize", 0, 
			"number of consecutive words in input one sample",
			&MuxOutputSampleSizeParam},
		{"MinimumChunk", 0, 
			"minimum number out input samples to process at once",
			&MuxMinimumChunkParam, 0, 0, 0, 0, 1},
		{0}
	};

	MuxNodeList = new EntityList;
	IntEntMux = new InteractiveEntity("Mux", MuxNodeList,
		MakeMux, InteractiveNode, "mux.h",
		0, "ProcessNode");
	IntEntMux->SetParameters(new UserParameters(MuxParArray));
	TheNodes->Append(IntEntMux);
} // end initalization

static UserEntity * MakeMux(OutTokens& Out, EntityReq Request,
	InteractiveEntity& IntNode,
	ArithType::ArithCapabilities arith)
{
	switch(Request) {
case EntityReqDescribe:

case EntityReqDescribeFull:
		Out.NextQuoteOut("Mux");
		Out.NextFillOut("takes");
		Out.NextQuoteOut("Channels");
		Out.NextFillOut("input channels and multiplexes these onto");
		Out.NextFillOut("a single output channel. Each input channel must have samples");
		Out.NextFillOut("consisting of");
		Out.NextQuoteOut("InputSampleSize");
		Out.NextFillOut("words. For example, complex data streams");
		Out.NextFillOut("will generally have two words in each sample. The output");
		Out.NextFillOut("channel will have samples of");
		Out.NextQuoteOut("OutputSampleSize");
		Out.NextFillOut("words.");
		Out.NewLine();
		break;

case EntityReqCreate:
	{
		const char * Name = IntNode.GetStringParameterValue("Name");
		int16 Channels =
			IntNode.GetIntParameterValue("Channels");
		int32 InputSampleSize =
			IntNode.GetIntParameterValue("InputSampleSize");
		int32 OutputSampleSize =
			IntNode.GetIntParameterValue("OutputSampleSize");
		int16 MinimumChunk =
			IntNode.GetIntParameterValue("MinimumChunk");
		return new Mux(Name, Channels, InputSampleSize, OutputSampleSize, MinimumChunk);

	}
	}
	return 0;
}

static InitObj LocalInit(MuxNodesInit, "Mux", "ProcessNode");

