#include "ObjProGui/user.h"
#include "ObjProNet/dfnode.h"

#include "ObjProUsr/cntnet.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 "ObjProUsr/buffer.h"
#include "ObjProGui/flwgrp.h"
#include "ObjProComGui/usercom.h"
#include "ObjProUsr/cbuf.h"
static EntityList * DataFlowNodeList = 0 ;
static InteractiveEntity * IntEntDataFlow ;
void DataFlowNodesInit();
DataFlow::DataFlow (const char * Name, ProcessNet&TheNet):
	NetControl(Name, TheNet)
,
	TheNet_1(&TheNet)
{
	if (!DataFlowNodeList) DataFlowNodesInit() ;
	DataFlowNodeList->Append(MakeDeclaredEntity(this, IntEntDataFlow)) ;
	InitArithType(TheArithType);
	NewMenuItem("DataFlow",GetName());
} // end constructor

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

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

DataFlow * DataFlowDef;

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

void DataFlow::Describe(OutTokens& Out, ListEntity Option)
{
	switch(Option) {
case ListSingleEntity:
		Out.NewLine();
		MakeDataFlow(Out,EntityReqDescribeFull,*IntEntDataFlow, (ArithType::ArithCapabilities) TheArithType);
		Out.NewLine();
		Out.NextQuoteOut("TheNet");
		Out.NextQuoteOut(GetTheNet()->GetName());
		Out.NextFillOut("is the `Network' to be controlled.");
		Out.NewLine();
		break;
case ListEntityMembers:
		Out.NextOut(GetName());
		break;
case ListGlobalClasses:
case ListEntityClasses:
		break ;
case ListSetParameterValues:
		IntEntDataFlow->GetOneParameter("TheNet")->
			EntityP->CurrentValue = TheNet_1;
		break;
	}
} // end  list entity switch

static ValueType * GraphDisplay(OutTokens& Out,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
case EntityReqDescribeFull:
		Out.NextFillOut("Member function");
		Out.NextQuoteOut("GraphDisplay");
		Out.NextFillOut("displays the network topology");
		Out.NextFillOut("and timing.");
		Out.NewLine();

	break ;
case EntityReqCall:
		{		int16 Option =
			Param->GetIntParameterValue("Option");

		((DataFlow * )This)->GraphDisplay(
		Option);		}
	}
	return 0;
}

static ValueType * Execute(OutTokens& Out,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
case EntityReqDescribeFull:
		Out.NextFillOut("Member function");
		Out.NextQuoteOut("Execute");
		Out.NextFillOut("executes the network being controlled.");
		Out.NextFillOut("It causes the signal generator (or first node in the network)");
		Out.NextFillOut("to produce a specified number");
		Out.NextFillOut("of input samples. Each node is executed for as many iterations");
		Out.NextFillOut("as possible given the available input data and output buffer");
		Out.NextFillOut("space. Execution halts when no node generates any new samples");
		Out.NextFillOut("after a complete pass throughout the network.");
		Out.NewLine();

	break ;
case EntityReqCall:
		{		int32 InputSamples =
			Param->GetIntParameterValue("InputSamples");

		((DataFlow * )This)->Execute(
		InputSamples);		}
	}
	return 0;
}

static ValueType * AssignBuffers(OutTokens& Out,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
case EntityReqDescribeFull:
		Out.NextFillOut("Member function");
		Out.NextQuoteOut("AssignBuffers");
		Out.NextFillOut("buffers to a completely defined");
		Out.NextFillOut("data flow network. The network is first checked for completeness.");
		Out.NextFillOut("Buffers will not be assigned if the network fails this test.");
		Out.NextFillOut("The single parameter of this function specifies the buffer");
		Out.NextFillOut("characteristics.");
		Out.NewLine();

	break ;
case EntityReqCall:
		{		BufferDescript&Descriptor =
			(BufferDescript& )*(BufferDescript *)Param->GetEntityParameterValue("Descriptor");

		((DataFlow * )This)->AssignBuffers(
		Descriptor);		}
	}
	return 0;
}

static ValueType * ClearBuffers(OutTokens& Out,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
case EntityReqDescribeFull:
		Out.NextFillOut("You can not change the topology of a network while buffers are");
		Out.NextFillOut("assigned. Member function");
		Out.NextQuoteOut("ClearBuffers");
		Out.NextFillOut("removes all buffers");
		Out.NextFillOut("so that the network can be edited or different buffers assigned.");
		Out.NewLine();

	break ;
case EntityReqCall:
		{
		((DataFlow * )This)->ClearBuffers(
		);		}
	}
	return 0;
}

static ValueType * ClearNetwork(OutTokens& Out,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
case EntityReqDescribeFull:
		Out.NextFillOut("Member function");
		Out.NextQuoteOut("ClearNetwork");
		Out.NextFillOut("removes all links in the network");
		Out.NextFillOut("being controlled. The nodes freed in this way can then be used");
		Out.NextFillOut("in a different network.");
		Out.NewLine();

	break ;
case EntityReqCall:
		{
		((DataFlow * )This)->ClearNetwork(
		);		}
	}
	return 0;
}

static int DataFlow_TheNet_CheckLegalThis_Func(CheckAction TheAction,
	OneParameter * TheParam, const OneParameter **,OutTokens *)
{
#line 72 "../cntnet.usr"
 
		Network * Obj ;
		NetControl * TheController ;
		switch (TheAction) {
case CheckActionCheck:
			if (!TheParam->EntityP) return 0 ;
			Obj = (Network *)
				TheParam->EntityP->CurrentValue ;
			TheController = Obj->GetTheController();
			if (!TheController) return 1;
			*Output + OutputCppHelp << "Network parameter `" <<
				Obj->GetName() << "'\n is already controlled by"
				<< " NetControl `" << TheController->GetName()
				<< "'.\n" ;
			return 0;
case CheckActionDescribe:
			{
				OutTokens Out(OutputCppHelp) ;
				Out.NextOut(
					"the network specified must not have a controller.") ;
			}	
			break ;
		}
		return 0 ;
	
#line 231 "../cntnet.cxx"

}

static DoCheckFunc DataFlow_TheNet_CheckLegalThis = {DataFlow_TheNet_CheckLegalThis_Func,  0};

void DataFlowNodesInit()
{
	if (DataFlowNodeList)  return ;

	static StringParam DataFlowNameParam =
		{"DataFlow", MakeNewEntityName, 0, LegalEntityName};
	static EntityParam DataFlowTheNetParam = {
		 "NetworkDef", "ProcessNet&", 0, 0};

	static OneParameter DataFlowParArray[] = {
		{"Name", 0, "node name", 0, 0, &DataFlowNameParam},
		{"TheNet", &DataFlow_TheNet_CheckLegalThis, 
			"Network to control",
			0, 0, 0, &DataFlowTheNetParam},
		{0}
	};

	static IntParam DataFlowGraphDisplayOptionParam = {
		 0, 0,  0,  0,  0,  2};
	static OneParameter GraphDisplayDataFlowList[] = {
		{"Option", 0, "display option (0 - short, 1 - full, 2- timing)"
			, &DataFlowGraphDisplayOptionParam},
		{0}
	};
	UserParameters * GraphDisplayMemberParam = new UserParameters
		(GraphDisplayDataFlowList);

	Procedure * MemberProcGraphDisplay = new Procedure("GraphDisplay", GraphDisplay,
		GraphDisplayMemberParam, "void", 0, "display network topology and timing");
	static IntParam DataFlowExecuteInputSamplesParam = {
		 128, 0,  0,  1, 0, 2.14748e+09};
	static OneParameter ExecuteDataFlowList[] = {
		{"InputSamples", 0, "input samples to process"
			, &DataFlowExecuteInputSamplesParam},
		{0}
	};
	UserParameters * ExecuteMemberParam = new UserParameters
		(ExecuteDataFlowList);

	Procedure * MemberProcExecute = new Procedure("Execute", Execute,
		ExecuteMemberParam, "void", 0, "execute network generating the specified number of samples");
	static EntityParam DataFlowAssignBuffersDescriptorParam = {
		 "CircBufDesDef", "BufferDescript&", 0, 0};
	static OneParameter AssignBuffersDataFlowList[] = {
		{"Descriptor", 0, "specify buffer characteristics"
			, 0, 0, 0, &DataFlowAssignBuffersDescriptorParam},
		{0}
	};
	UserParameters * AssignBuffersMemberParam = new UserParameters
		(AssignBuffersDataFlowList);

	Procedure * MemberProcAssignBuffers = new Procedure("AssignBuffers", AssignBuffers,
		AssignBuffersMemberParam, "void", 0, "assign buffers to a completely defined network");
	static OneParameter ClearBuffersDataFlowList[] = {
		{0}
	};
	UserParameters * ClearBuffersMemberParam = new UserParameters
		(ClearBuffersDataFlowList);

	Procedure * MemberProcClearBuffers = new Procedure("ClearBuffers", ClearBuffers,
		ClearBuffersMemberParam, "void", 0, "remove all buffers from network");
	static OneParameter ClearNetworkDataFlowList[] = {
		{0}
	};
	UserParameters * ClearNetworkMemberParam = new UserParameters
		(ClearNetworkDataFlowList);

	Procedure * MemberProcClearNetwork = new Procedure("ClearNetwork", ClearNetwork,
		ClearNetworkMemberParam, "void", 0, "delete all network links");
static ValueType * DataFlowMembers[6] ;
	int ii = 0 ;
	DataFlowMembers[ii++] = new ValueType(DecProcedure, MemberProcGraphDisplay) ;
	DataFlowMembers[ii++] = new ValueType(DecProcedure, MemberProcExecute) ;
	DataFlowMembers[ii++] = new ValueType(DecProcedure, MemberProcAssignBuffers) ;
	DataFlowMembers[ii++] = new ValueType(DecProcedure, MemberProcClearBuffers) ;
	DataFlowMembers[ii++] = new ValueType(DecProcedure, MemberProcClearNetwork) ;
	DataFlowMembers[ii++] = 0 ;
	DataFlowNodeList = new EntityList;
	IntEntDataFlow = new InteractiveEntity("DataFlow", DataFlowNodeList,
		MakeDataFlow, InteractiveScheduler, "cntnet.h",
		DataFlowMembers, "NetControl");
	IntEntDataFlow->SetParameters(new UserParameters(DataFlowParArray));
	TheNodes->Append(IntEntDataFlow);
} // end initalization

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

case EntityReqDescribeFull:
		Out.NextQuoteOut("DataFlow");
		Out.NextFillOut("is a `Scheduler' based on a data flow model. Its Only");
		Out.NextFillOut("argument is the");
		Out.NextQuoteOut("TheNet");
		Out.NextFillOut("to control.");
		Out.NewLine();
		break;

case EntityReqCreate:
	{
		const char * Name = IntNode.GetStringParameterValue("Name");
		ProcessNet&TheNet =
			(ProcessNet& )*(ProcessNet *)IntNode.GetEntityParameterValue("TheNet");
		return new DataFlow(Name, TheNet);

	}
	}
	return 0;
}

static InitObj LocalInit(DataFlowNodesInit, "DataFlow", "NetControl");

