#ifndef STREAM_H
#define STREAM_H

#include "unixtime.h"
#include "port.h"
#include "packet.h"
#include "generator.h"
#include "dataqueue.h"
#include <string.h>
#include "orbitapp.h"
//#include "oml_orbit_winlab_otg.h"


/**
 * Stream class is over a Port. It is the pseudo-application of the port.
 * Streams are orginized as "stream list" --- a double-link table structure. each stream has two pointers pointed
 * to the previous and next object in the stream list.
 */
//class OTGApp;

class Stream {
  friend class Port;
  friend class Packet;
  friend class Generator;
public:
 Stream(short id);
 Stream(short id, Generator *gen, Port* port, OrbitApp* app, int clockref=-1);
 Stream* prev_;
 Stream* next_;
 Packet *packetcache_;   ///< cache a packet here to send, only one packet pointer, not point to an array or queue.
 
protected:
 unsigned long seqno_;  ///< number of packets sent or received  by this stream	
 Generator *gen_;      ///< the generator to feed packets to this stream
 Port* port_;          /// the port for sending packets out.
 short streamid_; /// stream identifier. because one OTG get multiple streams.  correponding to a pair of unique IP/Port addresses
 //double starttime_;  ///< starting time of a stream
 UnixTime streamclock_; ///<Contorl the timing of stream
 OrbitApp *app_;    ///<each stream server the purpose for a certain application
 bool paused_;  ///< indicate whether stream is paused
	
public:
 /**
  * obtain the stream identifier
  */ 
 inline short getID(){return streamid_;}  
/**
 * Function to get the packet pointer of this stream
 */
inline Packet* getPacket(){ return packetcache_;}
/**
 * Function to get the current sequence number of this stream
 */   
inline unsigned long getSeqno(){return seqno_;}

//bool stampPktID();
bool loadPacket();
void startStream();
void pauseStream();
void resumeStream();  
void exitStream();
//void otgMeasureReport();
/**
 * Function to indicate the deliver time of this stream.
 *@return the next (future) deliver time of a packet recently cached (generated) for this stream. The multiplexing function has to compare those deliver times for each stream if there are multiple streams present.
 *@see Port::pickPacket
 */
 inline double getDeliverTime() { 
     if (packetcache_ != NULL) 
             return packetcache_->getTimeStamp();
     //otherwise
     return 0; // 0 should be an error!!! Exception
 }
 /**
  * Function to load a generator for a stream. Each stream must bind to a generator.
  */
 inline void loadGenerator(Generator *gen){ gen_ = gen; }  
 /**
  * Function to select a "port" to send a stream. Each stream must bind to a Port
  */
 inline void bindPort(Port *port){ port_ = port; }  
 inline Generator *getGenerator(){return gen_;}		      
 inline Port *getPort(){return port_;}
};


  
#endif

