/*
 *  netlnk.h from ObjectProDSP 0.1
 *  Copyright (C) 1994, Mountain Math Software. All rights reserved.
 *  
 *  This file is part of ObjectProDSP, a tool for Digital Signal
 *  Processing design, development and implementation. It is free
 *  software provided you use and distribute it under the terms of
 *  version 2 of the GNU General Public License as published
 *  by the Free Software Foundation. You may NOT distribute it or
 *  works derived from it or code that it generates under ANY
 *  OTHER terms.  In particular NONE of the ObjectProDSP system is
 *  licensed for use under the GNU General Public LIBRARY License.
 *  Mountain Math Software plans to offer a commercial version of
 *  ObjectProDSP for a fee. That version will allow redistribution
 *  of generated code under standard commercial terms.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of version 2 of the GNU General
 *  Public License along with this program. See file COPYING. If not
 *  or if you wish information on commercial versions and licensing
 *  write Mountain Math Software, P. O. Box 2124, Saratoga, CA 95070,
 *  USA, or send us e-mail at: support@mtnmath.com.
 *  
 *  You may also obtain the GNU General Public License by writing the
 *  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
 *  USA.  However if you received a copy of this program without the
 *  file COPYING or without a copyright notice attached to all text
 *  files, libraries and executables please inform Mountain Math Software.
 *  
 *  ObjectProDSP is a trademark of Mountain Math Software.
 */

#ifndef NETLNK_DOT_H
#define NETLNK_DOT_H
#include "ObjProGui/basic.h"
#include "ObjProGui/nodelst.h"

#include "ObjProDSP/portable.h"
#include "ObjProGen/debug.h"
#include "ObjProGen/slist.h"
#include "ObjProGui/timing.h"
#include "ObjProUsr/network.h"
#include "ObjProGui/netenm.h"
#include "ObjProDSP/timenum.h"

class DfNodeLink ;
class DfNode ;
class OutTokens ;
class GraphInfo ;
class StreamStr ;
class BufferOutInfo ;
class BufferDescript ;
class TargetReaderParameters ;
class TargetWriterParameters ;
class Adjustment ;

class DfNodeOutLink {
	friend DfNode ;
	DfNodeLink * OutLink ;
	int32 IncrementOut ;
	StreamStr * TheStreamStructure ;
	StreamStr * InitStreamStructure ;
	TargetWriterParameters*  TargetParameters ;
	TimingDescription Timing;
	TimingType timing_type ;
	int CkNull(const char * Nm) const;
	void init_stream(StreamStr * str);
public:
	DfNodeOutLink();
	~DfNodeOutLink();
	void Init();
	ErrCode Reset() ;
	void Set(int32 EltSz,int32 DeltaOut, int32 BlckSze = 1,
		TimingType type = TimingTypeLinear) ;
	void Set(int32 DeltaOut, StreamStr * stream_str,
		TimingType type = TimingTypeLinear) ;
	void SetElementSize(const char * Name, int32 EltSz) ;
	void SetFromDisk(const NodeOutChannelHeader& DiskState);
	void Clear() ; 
	int CheckComplete(const char * Name) ;
	void GraphDisplay(GraphInfo&);
	void Display();
	void NameDisplay() ;
	void SetLink(DfNodeLink * Lk) {OutLink = Lk ; }
	NodeOutChannelHeader * GetDiskState();
	int32 GetElementSize() const ;
	int32 GetChunkSize() const ;
	int32 GetBlockSize() const ;
	DfNodeLink * GetOutLink() const { return OutLink ; }
	int32 GetDataPerExe() const ;
	int32 GetCanExecute();
	int DoTail() ;
	void UpdateWrite(int32 Size); // Add Size words to read pointer
	void WriteBinary(UnsignedIntegerMachWord Data) ;
	MachWord * GetWriteBase() ;
	MachWord * GetWriteEnd()  ;
	MachWord * GetWritePtr() ;
	void WriteWord(MachWord Data) ;

	UnsignedIntegerMachWord * GetBinWriteBase()
		{return (UnsignedIntegerMachWord *) GetWriteBase();}
	UnsignedIntegerMachWord * GetBinWriteEnd()
		{return (UnsignedIntegerMachWord *) GetWriteEnd();}
	UnsignedIntegerMachWord * GetBinWritePtr()
		{return (UnsignedIntegerMachWord *) GetWritePtr();}

	int GetSpace() ;
	int GetContiguousSpace() ;
	void WriteCxWord(CxMachWord Data) ;
	DfNode * GetDriverNode() ;
	const char * GetDriverNodeName();
	const char * GetFreeNodeIn();
	const char * GetFreeNodeOut();
	DfNode * FindNode(const char *) ;
	DfNode * FindNode(const DfNode *) ;
	int32 GetIncrementOut() const {return IncrementOut;}
	TimingDescription * GetTiming() {return &Timing;}
	int AssignTiming(TimingDescription&, class DfNodeInLink * In);
	TimingCheck CheckFeedbackTiming(TimingDescription& Timing);
	int DoAdjust(TimingAdjustment& Adjust) ;
	int ChangeTiming(TimingAdjustment& Adjust) ;
	int DoChangeTiming(TimingAdjustment& Adjust) ;
	int GetNodeOutputChannel() ;
	int ClearBuffers();
	int DeleteAllLinks(const char * Name, class DfNodeList * List = 0);
	int GetDriverChannel() ;
	void AdjustSampleRate(TimingDescription& timing) ;
					     // adjust consistent with this
	TimingDescription& SetSampleRate(double Rate) ;
	StreamStr * GetStreamStr() {return TheStreamStructure;}
	void InitArithType(ArithType::ArithTypes type) ;
	void Adjust(const StreamStr * strm_str);
	TraverseResult Traverse(TraverseObject& obj) ;
	void ClearTraverse() ;
	void EmitBufferName(BufferOutInfo& Info);
	void EmitTargetBuffer(BufferOutInfo& Info);
	int IsFeedbackHead() const ;
	int IsInFeedbackLoop() const {return Timing.IsInFeedbackLoop();}
	int AnyConsumerOverlap() const ;
	int IsTargetDefined() const ;
	int IsTraverseComplete() const ;
	TargetAdjustState Adjust(Adjustment& TheAdjustment)
		{return OutLink->AdjustForward(TheAdjustment); }
	void SetTargetWriterParameters (TargetWriterParameters *  Params)
		{TargetParameters=Params ;}
	TargetWriterParameters * GetTargetWriterParameters() const
		{return TargetParameters;}
	void EmitTargetWriterParameters(OutTokens& Out) ;
	TraverseResult CheckTargetBufferSize(TraverseObject& obj);
	int32 GetMinBufferSize() const ;
	void remove_this_link();
	void disconnect();
	void DeassignBufferDescriptor(BufferDescript * des);
	void Unlink();
	void UnlinkChannel();
	void UnlinkReset();
	int is_linked(){return OutLink != 0;}
	int DoInitAfterLinked();
	void set_increment_out(int32 val);
	TimingType get_timing_type() const { return timing_type;}
} ;


class DfNodeInLink {
	friend DfNode ;
	class DfNodeLink * InLink ; 	
	int BufferChannelIndex ;	// Buffer output channel driving this
					// node input.
	int32 Overlap ;
	int32 IncrementIn ;
	int32 Delay ;
	StreamStr * TheStreamStructure ;
	StreamStr * InitStreamStructure ;
	TargetReaderParameters*  TargetParameters ;

	// int32 ElementSize ;
	int CkNull(const char * Nm) const;
	void init_stream(StreamStr * str);
public :
	void Init();
	ErrCode Reset();
	DfNodeInLink();
	virtual ~DfNodeInLink();
	void SetLink(DfNodeLink * Lk, int ChannelIndex)
		{InLink = Lk ; BufferChannelIndex = ChannelIndex ; }
	void SetElementSize(const char * Name, int32 EltSz) ;
	void Clear() ;
	int CheckComplete(const char * Name) ;
	void Display() ;
	void NameDisplay() ;
	void GraphDisplay(GraphInfo&);
	int32 GetElementSize() const ;
	int32 GetChunkSize() const ;
	int32 GetBlockSize() const ;
	void Set(int32 EltSz,int32 DeltaIn,int32 Ovlp,
		int32 Del) ;
	void Set(StreamStr * str_in, int32 DeltaIn, int32 Ovlp, int32 Del) ;
	NodeOutChannelHeader * GetDiskState();
	int32 GetDataPerExe() const ;
	int32 GetCanExecute(int not_first_time) ;
	void UpdateRead(int32 Size); // Add Size words to read pointer
	const MachWord * GetReadBase() ;
	const MachWord * GetReadEnd()  ;
	const MachWord * GetReadPtr() ;

	const UnsignedIntegerMachWord * GetBinReadBase()
		{return (const UnsignedIntegerMachWord *) GetReadBase();}
	const UnsignedIntegerMachWord * GetBinReadEnd()
		{return (const UnsignedIntegerMachWord *) GetBinReadEnd();}
	const UnsignedIntegerMachWord * GetBinReadPtr()
		{return (const UnsignedIntegerMachWord *) GetBinReadPtr();}

	MachWord ReadWord () ;
	UnsignedIntegerMachWord ReadBinary() ;

	int GetAvailableData() ;
	int GetContiguousAvailableData() ;
	CxMachWord ReadCxWord () ;
	DfNodeLink * GetInLink() const {return InLink; }
	int32 GetIncrementIn() const {return IncrementIn;}
	int32 GetOverlap() const {return Overlap;}
	int32 GetDelay() const {return Delay;}
	int32 GetInitData() const {return Delay - Overlap; }
	TimingDescription * GetTiming() ;
	void SetFromDisk(const NodeOutChannelHeader& DiskState);
	int ChangeTiming(TimingAdjustment& Adjust) ;
	int GetNodeInputChannel() ;
	DfNode * GetOutputNode() ;
	const char * GetOutputNodeName();
	const char * GetDriverNodeName();
	DfNode * GetDriverNode();
	DfNodeOutLink * GetDriverOutputChannel();
	int DeleteAllLinks(const char * Name, class DfNodeList * List = 0);
	void AdjustSampleRate(TimingDescription& timing) ;
	int CheckStreamStr(const StreamStr *);
	StreamStr * GetStreamStr() {return TheStreamStructure;}
	void InitArithType(ArithType::ArithTypes type) ;
	void Adjust(const StreamStr * strm_str);
	int GetBufferChannelIndex() const {return BufferChannelIndex;}
	void EmitBufferName(BufferOutInfo& Info);
	void SetTargetReaderParameters (TargetReaderParameters *  Params)
		{TargetParameters=Params ;}
	TargetReaderParameters * GetTargetReaderParameters() const
		{return TargetParameters;}
	void EmitTargetReaderParameters(OutTokens& Out) ;
	int IsTargetDefined() const {return TargetParameters!=0;}
	int IsTraverseComplete() const ;
	TargetBufferParameters * GetTargetBuffer() const ;
	TargetAdjustState AdjustTargetBuffer(int32 NewSize) ;
	void ClearTargetParameters();
	TraverseResult CheckTargetBufferSize(TraverseObject& obj);
	TargetAdjustState Adjust(Adjustment& TheAdjustment)
		{return InLink->AdjustBackward(TheAdjustment); }
	int32 GetMinBufferSize() const ;
	void remove_this_link(DfNode* driven, int channel) ;
	void disconnect();
	void decrement_buffer_channel(int new_value);
	void UnlinkDriven();
	void new_buffer_channel(int buffer_channel);
	void UnlinkChannel();
	void UnlinkReset();
	int is_linked(){return InLink != 0;}
	void set_increment_in(int32 val);
} ;


class DfNodeOut ;

class DfNodeOutList: public SingleList {
public:
	ErrCode Insert(DfNodeOut *nt) {return SingleList::Insert(nt);}
	ErrCode Append(DfNodeOut *nt) {return SingleList::Append(nt);}
	class DfNodeOut * Get()   {return (DfNodeOut *) SingleList::Get();}
	DfNodeOutList(){;}
	DfNodeOutList(DfNodeOut *nt):
		SingleList(nt) {}
	void Display();
	void NameDisplay();
	int CheckComplete(const char * name) ;
	int Size(){return SingleList::Size();}
	void Clear() {SingleList::Clear();}
	~DfNodeOutList() {Clear();}
	void remove_link(DfNode* driven, int input_channel);
} ;

class DfNodeOutIterator: public SingleListIterator {
public:
	DfNodeOutIterator(DfNodeOutList& df):
		SingleListIterator((SingleList&) df){}
	DfNodeOut * operator()()
		{return (DfNodeOut *) Next();}
};


// GetTiming inline routines

inline TimingDescription * DfNode::GetTiming(int OutChannel)
	{return OutLinks[OutChannel].GetTiming(); }

inline TimingDescription * DfNodeIn::GetTiming(){return TheNode->GetTiming(Index);}

inline TimingDescription * DfNodeLink::GetTiming()
	{return InputLink->GetTiming();}

inline TimingDescription * DfNodeInLink::GetTiming()
	{return InLink->GetTiming();}

inline DfNode * DfNodeOutLink::GetDriverNode() {return OutLink->GetInputNode();}

inline int DfNodeInLink::GetNodeInputChannel() {return InLink ?
		InLink->GetOutputNodeInputChannel(BufferChannelIndex) : -1;}

inline int DfNodeOutLink::GetNodeOutputChannel()
		{return OutLink ? OutLink->GetInputNodeOutputChannel() : -1;}

#endif /* #ifdef NETLNK_DOT_H */
