#include "ObjProNet/dfnode.h"

#include "ObjProUsr/block.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 "ObjProComGui/cgidbg.h"
#include "ObjProGui/yacintfc.h"
static EntityList * BlockNodeList = 0 ;
static InteractiveEntity * IntEntBlock ;
void BlockNodesInit();
Block::Block (const char * Name, int16 ElementSize, int16 BlockSize, 
		int16 OutputArithmetic):
	ProcessNodeStr(Name, 1, 1, 
	 new StreamStr(SizeVariable , SizeVariable , ArithType::ArithCapabilityAny), 
	 new StreamStr(ElementSize , BlockSize , (OutputArithmetic == 2 ? ArithType::ArithFloat : (OutputArithmetic == 1 ? ArithType::ArithInt32 : ArithType::ArithTypeUndefined))), 0, 1, 1, 0, 0, TimingTypeLinear)
,
	ElementSize_1(ElementSize),
	BlockSize_2(BlockSize),
	OutputArithmetic_3(OutputArithmetic)
{
	if (!BlockNodeList) BlockNodesInit() ;
	BlockNodeList->Append(MakeDeclaredEntity(this, IntEntBlock)) ;
	InitArithType(TheArithType);
	NewMenuItem("Block",GetName());
#line 88 "../block.usr"
 
	static_ctor();
#line 36 "../block.cxx"
#line 92 "../block.usr"
 
	ctor();
#line 40 "../block.cxx"
} // end constructor

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

ErrCode Block::EmitStaticInit(OutTokens& Out)
{
	ostream& Outs = *(Out.GetStream());
	Outs << "static int BlockStaticInitthe_convert_type_" << GetName() << " = ";	
	OutStringStaticValue(Outs,"int", &(the_convert_type)) ;

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

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

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

Block * BlockDef;

ErrCode Block::DoNode(int32 k)
{
#line 114 "../block.usr"
 
	return kernel(k);
#line 80 "../block.cxx"
} // end kernel code

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

void Block::Describe(OutTokens& Out, ListEntity Option)
{
	switch(Option) {
case ListSingleEntity:
		Out.NewLine();
		MakeBlock(Out,EntityReqDescribeFull,*IntEntBlock, (ArithType::ArithCapabilities) TheArithType);
		Out.NewLine();
		Out.NextQuoteOut("ElementSize");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetElementSize()));
		Out.NextFillOut(")");
		Out.NextFillOut("is the number of words in each output sample");
		Out.NextFillOut("(1 for real, 2 for complex or larger for other purposes).");
		Out.NextQuoteOut("BlockSize");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetBlockSize()));
		Out.NextFillOut(")");
		Out.NextFillOut("is the number of samples in each output block. If");
		Out.NextFillOut("set to 1 the output is not blocked.");
		Out.NextQuoteOut("Block");
		Out.NextFillOut("can read data from any input arithmetic type.");
		Out.NextQuoteOut("OutputArithmetic");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetOutputArithmetic()));
		Out.NextFillOut(")");
		Out.NextFillOut("selects the output arithmetic type. On a");
		Out.NextFillOut("32 bit simulator");
		Out.NextQuoteOut("Block");
		Out.NextFillOut("can write output as either 32 bit");
		Out.NextFillOut("floating point or 32 bit fixed point. Choose 0 to write");
		Out.NextFillOut("output in the default type of the simulator, 1 for 32 bit");
		Out.NextFillOut("integers and 2 for 32 bit floating point.");
		Out.NewLine();
		break;
case ListEntityMembers:
		Out.NextOut(GetName());
		break;
case ListGlobalClasses:
case ListEntityClasses:
		break ;
case ListSetParameterValues:
		IntEntBlock->GetOneParameter("ElementSize")->
			IntP->CurrentValue = ElementSize_1;
		IntEntBlock->GetOneParameter("BlockSize")->
			IntP->CurrentValue = BlockSize_2;
		IntEntBlock->GetOneParameter("OutputArithmetic")->
			IntP->CurrentValue = OutputArithmetic_3;
		break;
	}
} // end  list entity switch

void BlockNodesInit()
{
	if (BlockNodeList)  return ;

	static StringParam BlockNameParam =
		{"Block", MakeNewEntityName, 0, LegalEntityName};
	static IntParam BlockElementSizeParam = {
		 2, 0,  0,  1, 0, 32767};
	static IntParam BlockBlockSizeParam = {
		 1, 0,  0,  1, 0, 32767};
	static IntParam BlockOutputArithmeticParam = {
		 0, 0,  0,  0,  0,  2};

	static OneParameter BlockParArray[] = {
		{"Name", 0, "node name", 0, 0, &BlockNameParam},
		{"ElementSize", 0, 
			"output element size",
			&BlockElementSizeParam},
		{"BlockSize", 0, 
			"output block size",
			&BlockBlockSizeParam, 0, 0, 0, 0, 1},
		{"OutputArithmetic", 0, 
			"output data: 0 - MachWord, 1 - int32, 2 - float",
			&BlockOutputArithmeticParam, 0, 0, 0, 0, 1},
		{0}
	};

	BlockNodeList = new EntityList;
	IntEntBlock = new InteractiveEntity("Block", BlockNodeList,
		MakeBlock, InteractiveNode, "block.h",
		0, "ProcessNodeStr");
	IntEntBlock->SetParameters(new UserParameters(BlockParArray));
	TheNodes->Append(IntEntBlock);
} // end initalization

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

case EntityReqDescribeFull:
		Out.NextQuoteOut("Block");
		Out.NextFillOut("converts its input stream to an output stream with");
		Out.NextQuoteOut("ElementSize");
		Out.NextFillOut("words per sample and");
		Out.NextQuoteOut("BlockSize");
		Out.NextFillOut("samples per block.");
		Out.NextFillOut("The sample size and block size of the input data stream are");
		Out.NextFillOut("ignored. The stream is treated as if it were an unblocked real");
		Out.NextFillOut("data stream. On a 32 bit simulator");
		Out.NextQuoteOut("Block");
		Out.NextFillOut("can convert an");
		Out.NextFillOut("integer or floating point input channel to floating point or");
		Out.NextFillOut("integer output. If overflow occurs in converting integer to");
		Out.NextFillOut("floating point the result will saturate and no warning message");
		Out.NextFillOut("will be given.  Some nodes that read disk files only generate");
		Out.NextFillOut("a real data stream. If such a node is used to read complex data");
		Out.NextQuoteOut("Block");
		Out.NextFillOut("can do the needed transformation.  If a node is used to");
		Out.NextFillOut("read FFT output from another process you can use");
		Out.NextQuoteOut("BlockSize");
		Out.NextFillOut("to structure the data so it will be plotted correctly with one");
		Out.NextFillOut("FFT window per plot. If");
		Out.NextQuoteOut("BlockSize");
		Out.NextFillOut("is 1 the output is not blocked.");
		Out.NewLine();
		break;

case EntityReqCreate:
	{
		const char * Name = IntNode.GetStringParameterValue("Name");
		int16 ElementSize =
			IntNode.GetIntParameterValue("ElementSize");
		int16 BlockSize =
			IntNode.GetIntParameterValue("BlockSize");
		int16 OutputArithmetic =
			IntNode.GetIntParameterValue("OutputArithmetic");
		return new Block(Name, ElementSize, BlockSize, OutputArithmetic);

	}
	}
	return 0;
}

static InitObj LocalInit(BlockNodesInit, "Block", "ProcessNodeStr");

