#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 "ObjProArith/hrdcmp.h"
#include "ObjProArithGen/artherr.h"
#include "ObjProDSPint/netlnk.h"
#include "ObjProNet/dfnode.h"

#include "ObjProUsr/fndtail.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 * FindStartTailNodeList = 0 ;
static InteractiveEntity * IntEntFindStartTail ;
void FindStartTailNodesInit();
FindStartTail::FindStartTail (const char * Name, double LowerBound, double UpperBound, 
		int16 Flags, int32 Skip):
	ProcessNodeStr(Name, 1, 1, 
	 new StreamStr(SizeVariable , SizeVariable , ArithType::ArithCapabilityAny), new StreamStr(StreamNotSet), 0, 1, 1, 0, 0, TimingTypeRandom)
,
	LowerBound_1(LowerBound),
	UpperBound_2(UpperBound),
	Flags_3(Flags),
	Skip_4(Skip)
{
	if (!FindStartTailNodeList) FindStartTailNodesInit() ;
	FindStartTailNodeList->Append(MakeDeclaredEntity(this, IntEntFindStartTail)) ;
	InitArithType(TheArithType);
	NewMenuItem("FindStartTail",GetName());
#line 97 "../fndtail.usr"
 
	TailFound = 0 ;
	DataToSkip = GetSkip() ;
#line 45 "../fndtail.cxx"
} // end constructor

ErrCode FindStartTail::EmitStaticCtorParameters(OutTokens& Out)
{
	ostream& Outs = *(Out.GetStream());
	Outs << ",\n\tFindStartTailStaticInitbinary_read_flag_" << GetName() << "";
	return OK;
}

ErrCode FindStartTail::EmitStaticInit(OutTokens& Out)
{
	ostream& Outs = *(Out.GetStream());
	Outs << "static int FindStartTailStaticInitbinary_read_flag_" << GetName() << " = ";	
	OutStringStaticValue(Outs,"int", &(binary_read_flag)) ;

	Outs << ";\n";
	return OK;
}

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

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

FindStartTail * FindStartTailDef;

ErrCode FindStartTail::DoNode(int32 k)
{
#line 116 "../fndtail.usr"
 
	int j ;
	// LogOut << "SampleDelay(" << k << "): DelHistory = " << DelHistory <<
	//	", Delta = " << GetDelta() << "\n" ;
	for (int32 i=0 ;i < k ; i++)
	    for (int b=0; b< GetBlockSize(); b++)
		if (DataToSkip) {
			for (j = 0 ; j < GetEltSize(); j++) if (binary_read_flag) ReadInteger() ; else ReadWord();
			DataToSkip-- ;
		} else if (TailFound) for (j = 0 ; j < GetEltSize(); j++) {
			if (binary_read_flag) WriteInteger(ReadInteger()) ; else  WriteWord(ReadWord());
		} else for (j = 0 ; j < GetEltSize(); j++) {
			IntegerMachWord bin_word ;
			MachWord word ;
			if (binary_read_flag) bin_word = (IntegerMachWord) ReadInteger();
			else word = ReadWord() ;
			if (!TailFound) if (binary_read_flag) {
				if (sizeof(MachWord)==4) {
					int32 iword = *(int32 *) &bin_word ;
					int GreaterTest =
						(double) iword > GetLowerBound() ||
						(GetFlags()&2) ;
					int LesserTest =
						(double) iword < GetUpperBound() ||
						(GetFlags()&4) ;
					if (LesserTest && GreaterTest)
							TailFound = 1 ;
				} else if (sizeof(MachWord) == 2) {
					int16 iword = *(int16 *) &bin_word ;
					int GreaterTest =
						(double) iword > GetLowerBound() ||
						(GetFlags()&2) ;
					int LesserTest =
						(double) iword < GetUpperBound() ||
						(GetFlags()&4) ;
					if (LesserTest && GreaterTest)
							TailFound = 1 ;
				} else DbgError("FindStartTail::Kernel",
					"bad data type");
			} else {
				int GreaterTest = word.val() > GetLowerBound() ||
					(GetFlags()&2) ;
				int LesserTest = word.val() < GetUpperBound() ||
						(GetFlags()&4) ;
				if (LesserTest && GreaterTest) TailFound = 1 ;
			}
			if (TailFound == 1) {
				if (j) continue ;
				else TailFound = 2 ;
			}
			if (TailFound) if (binary_read_flag) WriteInteger(bin_word) ; else WriteWord(word);
		}
	return OK ;
#line 136 "../fndtail.cxx"
} // end kernel code

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

void FindStartTail::Describe(OutTokens& Out, ListEntity Option)
{
	switch(Option) {
case ListSingleEntity:
		Out.NewLine();
		MakeFindStartTail(Out,EntityReqDescribeFull,*IntEntFindStartTail, (ArithType::ArithCapabilities) TheArithType);
		Out.NewLine();
		Out.NextFillOut("A sample containing an initial element >");
		Out.NextQuoteOut("LowerBound");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetLowerBound()));
		Out.NextFillOut(")");
		Out.NextFillOut("will be ignored.");
		Out.NextFillOut("Once one element of a sample has passed both bound tests");
		Out.NextFillOut("all later samples will be passed to the next node. If the first element in");
		Out.NextFillOut("a sample passes the tests then that sample will be passed.");
		Out.NextFillOut("An initial element <");
		Out.NextQuoteOut("UpperBound");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetUpperBound()));
		Out.NextFillOut(")");
		Out.NextFillOut("will be ignored.");
		Out.NextFillOut("Once one element of a sample has passed both bound tests it and");
		Out.NextFillOut("all later samples will be passed to the next node. If the first element in");
		Out.NextFillOut("a sample passes the tests then that sample will be passed.");
		Out.NextFillOut("If bit 2 is");
		Out.NextFillOut("set then the first bounds test is ignored.");
		Out.NextFillOut("If bit 3 is set the second test is ignored.");
		Out.NextFillOut("If both bits 2 and 3 are set you can skip a fixed number");
		Out.NextFillOut("of samples by setting");
		Out.NextQuoteOut("Skip");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetSkip()));
		Out.NextFillOut(")");
		Out.NextFillOutConcat(".");
		Out.NextFillOut("The first");
		Out.NextQuoteOut("Skip");
		Out.NextFillOut("samples are read but not written.");
		Out.NewLine();
		break;
case ListEntityMembers:
		Out.NextOut(GetName());
		break;
case ListGlobalClasses:
case ListEntityClasses:
		break ;
case ListSetParameterValues:
		IntEntFindStartTail->GetOneParameter("LowerBound")->
			FloatP->CurrentValue = LowerBound_1;
		IntEntFindStartTail->GetOneParameter("UpperBound")->
			FloatP->CurrentValue = UpperBound_2;
		IntEntFindStartTail->GetOneParameter("Flags")->
			IntP->CurrentValue = Flags_3;
		IntEntFindStartTail->GetOneParameter("Skip")->
			IntP->CurrentValue = Skip_4;
		break;
	}
} // end  list entity switch

void FindStartTailNodesInit()
{
	if (FindStartTailNodeList)  return ;

	static StringParam FindStartTailNameParam =
		{"FindStartTail", MakeNewEntityName, 0, LegalEntityName};
	static FloatParam FindStartTailLowerBoundParam = {
		 0, 0, 0, -1e+100, 0, 1e+100};
	static FloatParam FindStartTailUpperBoundParam = {
		 0, 0, 0, -1e+100, 0, 1e+100};
	static IntParam FindStartTailFlagsParam = {
		 0, 0, 0, -32767, 0, 32767};
	static IntParam FindStartTailSkipParam = {
		 0, 0,  0,  0, 0, 2.14748e+09};

	static OneParameter FindStartTailParArray[] = {
		{"Name", 0, "node name", 0, 0, &FindStartTailNameParam},
		{"LowerBound", 0, 
			"ignore initial input > `LowerBound",
			0, &FindStartTailLowerBoundParam},
		{"UpperBound", 0, 
			"ignore initial input > `UpperBound",
			0, &FindStartTailUpperBoundParam},
		{"Flags", 0, 
			"specieal options",
			&FindStartTailFlagsParam, 0, 0, 0, 0, 1},
		{"Skip", 0, 
			"Samples to skip before processing any data",
			&FindStartTailSkipParam, 0, 0, 0, 0, 1},
		{0}
	};

	FindStartTailNodeList = new EntityList;
	IntEntFindStartTail = new InteractiveEntity("FindStartTail", FindStartTailNodeList,
		MakeFindStartTail, InteractiveNode, "fndtail.h",
		0, "ProcessNodeStr");
	IntEntFindStartTail->SetParameters(new UserParameters(FindStartTailParArray));
	TheNodes->Append(IntEntFindStartTail);
} // end initalization

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

case EntityReqDescribeFull:
		Out.NextQuoteOut("FindStartTail");
		Out.NextFillOut("copies its input to its output. Data is copied");
		Out.NextFillOut("at the first sample with value >");
		Out.NextQuoteOut("LowerBound");
		Out.NextFillOut("and <");
		Out.NextQuoteOut("UpperBound");
		Out.NextFillOutConcat(". If the input data is integer type on a floating point");
		Out.NextFillOut("simulator signed input is assumed.");
		Out.NextFillOut("If the data is complex then the magnitude of each component of the");
		Out.NextFillOut("each sample is checked. The first full sample after the test is");
		Out.NextFillOut("passed is output.");
		Out.NewLine();
		break;

case EntityReqCreate:
	{
		const char * Name = IntNode.GetStringParameterValue("Name");
		double LowerBound =
			IntNode.GetFloatParameterValue("LowerBound");
		double UpperBound =
			IntNode.GetFloatParameterValue("UpperBound");
		int16 Flags =
			IntNode.GetIntParameterValue("Flags");
		int32 Skip =
			IntNode.GetIntParameterValue("Skip");
		return new FindStartTail(Name, LowerBound, UpperBound, Flags, Skip);

	}
	}
	return 0;
}

static InitObj LocalInit(FindStartTailNodesInit, "FindStartTail", "ProcessNodeStr");

