#include <complex.h>
#include <signal.h>
#include "ObjProDSP/portable.h"
#include "ObjProComGui/usercom.h"
#include "ObjProArith/hrdarth.h"
#include "ObjProArithGen/arthfnc.h"
#include "ObjProComGui/cgidbg.h"
#include "ObjProArithGen/artherr.h"
#include "ObjProDSPint/netlnk.h"
#include "ObjProNet/dfnode.h"

#include "ObjProUsr/delay.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"
static EntityList * SampleDelayNodeList = 0 ;
static InteractiveEntity * IntEntSampleDelay ;
void SampleDelayNodesInit();
SampleDelay::SampleDelay (const char * Name, int32 Delta, MachWord FillValue):
	ProcessNodeStr(Name, 1, 1, new StreamStr(StreamNotSet), 
	new StreamStr(StreamNotSet), Delta, 1, 1, 0, 0, TimingTypeLinear)
,
	Delta_1(Delta),
	FillValue_2(FillValue)
{
	if (!SampleDelayNodeList) SampleDelayNodesInit() ;
	SampleDelayNodeList->Append(MakeDeclaredEntity(this, IntEntSampleDelay)) ;
	InitArithType(TheArithType);
	NewMenuItem("SampleDelay",GetName());
#line 42 "../delay.usr"
 
	DelHistory = 0 ;
#line 40 "../delay.cxx"
} // end constructor

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

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

SampleDelay * SampleDelayDef;

ErrCode SampleDelay::DoNode(int32 k)
{
#line 57 "../delay.usr"
 
	// LogOut << "SampleDelay(" << k << "): DelHistory = " << DelHistory <<
	//	", Delta = " << GetDelta() << "\n" ;
	int32 ElementSize = GetInLink(0)->GetElementSize();
	int32 j;
	for (int32 i=0 ;i < k ; i++) {
		if (DelHistory < GetDelta()) {
			DelHistory ++ ;
			for (j = 0 ; j < ElementSize; j++) {
				WriteWord(GetFillValue());
				// cout << "SampleDelay Done " << i << "\n" ;
			}
			continue ;
		}
		for (j = 0 ; j < GetEltSize(); j++) {
			WriteWord(ReadWord());
			// cout << "SampleDelay Done " << i << "\n" ;
		}
	}
	return OK ;
#line 81 "../delay.cxx"
} // end kernel code

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

void SampleDelay::Describe(OutTokens& Out, ListEntity Option)
{
	switch(Option) {
case ListSingleEntity:
		Out.NewLine();
		MakeSampleDelay(Out,EntityReqDescribeFull,*IntEntSampleDelay, (ArithType::ArithCapabilities) TheArithType);
		Out.NewLine();
		Out.NextQuoteOut("Delta");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetDelta()));
		Out.NextFillOut(")");
		Out.NextFillOut("specifies the number of samples the");
		Out.NextFillOut("output signal will be delayed relative to the input.");
		Out.NextQuoteOut("FillValue");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetFillValue()));
		Out.NextFillOut(")");
		Out.NextFillOut("is the value to be output for each");
		Out.NextFillOut("sample component for the first");
		Out.NextQuoteOut("Delta");
		Out.NextFillOut("samples.");
		Out.NewLine();
		break;
case ListEntityMembers:
		Out.NextOut(GetName());
		break;
case ListGlobalClasses:
case ListEntityClasses:
		break ;
case ListSetParameterValues:
		IntEntSampleDelay->GetOneParameter("Delta")->
			IntP->CurrentValue = Delta_1;
		MachWord  * FillValue_2_Ptr = new MachWord ;
		FillValue_2_Ptr = &FillValue_2;
		IntEntSampleDelay->GetOneParameter("FillValue")->
			ArrayP->CurrentValue = 
		(new ArrayData)->SetArrayData(-1, DecMachWord, (void *) FillValue_2_Ptr);
		break;
	}
} // end  list entity switch

void SampleDelayNodesInit()
{
	if (SampleDelayNodeList)  return ;

	static StringParam SampleDelayNameParam =
		{"SampleDelay", MakeNewEntityName, 0, LegalEntityName};
	static IntParam SampleDelayDeltaParam = {
		 1, 0,  0,  0, 0, 2.14748e+09};
	static  CastMachWord SampleDelayFillValueDefaultObject =
		{0} ;


	static ArrayData SampleDelayFillValueDefaultValue = {-1, DecMachWord,
		(void *) &SampleDelayFillValueDefaultObject};

	static  CastMachWord SampleDelayFillValueLowerArrayBound =
		{DEF_MACH_WORD_MIN} ;

	static  CastMachWord SampleDelayFillValueUpperArrayBound =
		{DEF_MACH_WORD_MAX} ;

	static ArrayParam SampleDelayFillValueParam = {
		DecMachWord, &SampleDelayFillValueDefaultValue,
		0, 0, (void *) &SampleDelayFillValueLowerArrayBound, 0,
		(void *) &SampleDelayFillValueUpperArrayBound};

	static OneParameter SampleDelayParArray[] = {
		{"Name", 0, "node name", 0, 0, &SampleDelayNameParam},
		{"Delta", 0, 
			"signal delay in samples",
			&SampleDelayDeltaParam},
		{"FillValue", 0, 
			"value to output before input data is copied",
			0, 0, 0, 0,
			&SampleDelayFillValueParam, 1},

		{0}
	};

	SampleDelayNodeList = new EntityList;
	IntEntSampleDelay = new InteractiveEntity("SampleDelay", SampleDelayNodeList,
		MakeSampleDelay, InteractiveNode, "delay.h",
		0, "ProcessNodeStr");
	IntEntSampleDelay->SetParameters(new UserParameters(SampleDelayParArray));
	TheNodes->Append(IntEntSampleDelay);
} // end initalization

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

case EntityReqDescribeFull:
		Out.NextQuoteOut("SampleDelay");
		Out.NextFillOut("initially copies");
		Out.NextQuoteOut("Delta");
		Out.NextFillOut("samples (with all components");
		Out.NextFillOut("set equal to");
		Out.NextQuoteOut("FillValue");
		Out.NextFillOutConcat(") to its output. After that it simply");
		Out.NextFillOut("copies its input to its output. This results in a delay");
		Out.NextFillOut("if");
		Out.NextQuoteOut("Delta");
		Out.NextFillOut("samples.");
		Out.NewLine();
		break;

case EntityReqCreate:
	{
		const char * Name = IntNode.GetStringParameterValue("Name");
		int32 Delta =
			IntNode.GetIntParameterValue("Delta");
		MachWord FillValue =
			*(MachWord * ) IntNode.GetArrayParameterValue("FillValue");
		return new SampleDelay(Name, Delta, FillValue);

	}
	}
	return 0;
}

static InitObj LocalInit(SampleDelayNodesInit, "SampleDelay", "ProcessNodeStr");

