#ifndef COSY_MTcpIpIO
#define COSY_MTcpIpIO

#ifndef COSY_MsgQueue
#include "msgqueue.h"
#endif
#ifndef MARS_MTime
#include "MTime.h"
#endif
#ifndef ROOT_TMutex
#include <TMutex.h>
#endif


class TString;
class TSocket;
class TServerSocket;

// A generalized class for receiving over tcp/ip
class MTcpIpI : public MThread
{
private:
    Int_t  fPortRx;     // Port on which to listen for connections
    Int_t  fTimeout;    // [ms] Timeout to listen for data to be received

    Bool_t fConnectionEstablished;

    MTime  fLast;

    Bool_t WaitForData(TSocket &sock);
    void   WaitForConnection(TServerSocket &server);

    Int_t Thread();

    virtual Bool_t ReadSocket(TSocket &rx) = 0;

public:
    MTcpIpI(Int_t rx, UInt_t timeout=5000) : MThread(Form("MTcpIpI::%d", rx)), fPortRx(rx), fTimeout(timeout), fConnectionEstablished(kFALSE) { /*RunThread();*/ }
    ~MTcpIpI() { CancelThread(); }

    Bool_t IsConnectionEstablished() const { return fConnectionEstablished; }
};


// A generalized class for sending over tcp/ip
class MTcpIpO : public MThread
{
private:
    TSocket *fTxSocket;
    TMutex   fMutex;

    Int_t fPortTx;

    Int_t Thread();

public:
    MTcpIpO(const char *addr, Int_t tx);
    ~MTcpIpO();

    static TString GetSocketAddress(const TSocket &s);
    static bool    SendFrame(TSocket &tx, const char *msg, int len);
    static bool    SendFrame(const char *addr, int port, const char *msg, int len);

    bool Send(const char *msg, int len);
};

// This class es espcially meant to receive and send ascii messages
class MTcpIpIO : public MTcpIpI, public MTcpIpO
{
private:
    Bool_t ReadSocket(TSocket &rx);

public:
    MTcpIpIO(const char *addr, Int_t tx, Int_t rx, UInt_t timeout=5000);
    ~MTcpIpIO();

    virtual bool InterpreteStr(TString str);
};

#endif
