/* LICENSE:
  =========================================================================
    CMPack'04 Source Code Release for OPEN-R SDK 1.1.5-r2 for ERS7
    Copyright (C) 2004 Multirobot Lab [Project Head: Manuela Veloso]
    School of Computer Science, Carnegie Mellon University
    All rights reserved.
  ========================================================================= */

#ifndef INCLUDED_WLOut_h
#define INCLUDED_WLOut_h

#include <OPENR/OObject.h>
#include <OPENR/OSubject.h>
#include <OPENR/OObserverVector.h>

class PacketMux;
class PacketStream;
class PacketStreamCollection;
class RobotDataPacket;

#include "def.h"
#include "../headers/AperiosSharedMem.h"
#include "../headers/DogTypes.h"
#include "../headers/SharedMem.h"
#include "../headers/WaveLAN.h"

/* We need to skip a couple of bytes for header
   information in the message. Currently this is just
   the size of the buffer we're sending.
*/
static const ulong NetworkBufferDataStart = sizeof(NetMsgHeader);

/* This is the size of the buffer that is
   used to hold data before it is put into
   a message and sent over the network.
*/
static const ulong NetworkBufferSize = 1024;

/* This is the size of the buffer that is
   used to hold a copy of the header
   information before being copied to the
   network buffer.
*/
static const ulong HeadBufferSize = 30; // anything longer than the actual size should work

//ulong state = 0;




//******************************************************
// ECHOSERVER INCLUDES:

#include <OPENR/OObject.h>
#include <OPENR/OSubject.h>
#include <OPENR/OObserver.h>
#include "TCPConnection.h"

// Setting this to 10 instead of 1 seems to fix random crashes.
// I don't know why. :....O(
#define ECHOSERVER_CONNECTION_MAX  10
#define ECHOSERVER_BUFFER_SIZE     1024
#define ECHOSERVER_PORT            54321

//*********************************************************



class WLOut : public OObject {
 private:

  /* The offset of the next available byte in
     the network buffer.
  */
  ulong netBufIndex;
  uchar *netBuffer;
  uchar headBuffer[HeadBufferSize];

  static const int MaxDataBufs=4;
  int numBufs;
  uchar *dataBuf[MaxDataBufs];
  ulong dataLength[MaxDataBufs];
  
  uchar SenderID;

public:
  OSubject*          subject[numOfSubject];
  OObserverVector*   observer[numOfObserver];
 
  WLOut();
  ~WLOut() {}

  //
  //  OPEN-R Methods
  //
  virtual OStatus DoInit(const OSystemEvent&);
  virtual OStatus DoStart(const OSystemEvent&);
  virtual OStatus DoStop(const OSystemEvent&);
  virtual OStatus DoDestroy(const OSystemEvent&);

  //
  // Inter Object Communication Methods 
  //
  void ReadyRegisterRegion(const OReadyEvent &event);
  void ReadyRequestRegion(const OReadyEvent &event);
  void NetTransmit(const OReadyEvent &event);
  void GotMemRegion(const ONotifyEvent &event);

  void ProcessBuffer(void *msg);
  void processBuffer();

  void sendOutputBuffer();

  void requestRegions();

  //**************************************************
    //  ECHOSERVER FUNCTIONS:

    void ListenCont (void* msg);
    void SendCont   (void* msg);
    void ReceiveCont(void* msg);
    void CloseCont  (void* msg);

    //************************************************

private:
  // methods
  void bufferData(uchar *data, ulong length);
  void bufferHeader(RobotDataPacket *packet);
  // return true if needs to wait on observer
  bool sendPacket(RobotDataPacket *packet);
  // return true if needs to wait on observer
  bool sendBuffers();

  // send buffered data over the network
  // return true if needs to wait on observer
  bool flush();
  void startTimer();

  // return true if sent some data, false if no data to send
  bool sendNetBuffer();

  // data
  bool quickCheck;
  bool gotMessage;
  bool timerStarted;
  bool needToSendBuffer;
  SMMSharedMemRegion outTextRgn;
  bool requestedRegion[MemoryId::NUM_MEMORY_IDS];
  SMMSharedMemRegion mainOutMemRgn;
  SMMSharedMemRegion motionOutMemRgn;
  SMMSharedMemRegion loggerOutMemRgn;
  PacketStreamCollection *mainOutPSC;
  PacketStreamCollection *motionOutPSC;
  PacketStreamCollection *loggerOutPSC;
  PacketMux *mux;
  void *baseAddr;



  //******************************************
    //  ECHOSERVER FUNCTIONS:

    OStatus Listen (int index);
    OStatus Send   (int index);
    OStatus Receive(int index);
    OStatus Close  (int index);
    OStatus InitTCPConnection(int index);

    void proc();

    antStackRef    ipstackRef;
    TCPConnection  connection[ECHOSERVER_CONNECTION_MAX];

    //******************************************
};

#endif
