#ifndef __NETUTILS_H__
#define __NETUTILS_H__  

#include "assoc.h"

class TConnection;
typedef unsigned long CONNID;

typedef int (*ConnectionFunction)(TConnection& conn, void* pJolly);

class TLanManager : public TObject
{                
  TAssoc_array m_mapConn;

protected:
  CONNID AddConnection(TConnection* pConn);

  virtual TConnection* OnCreateConnection(CONNID id);                           
  virtual bool OnRemoveConnection(CONNID id);

public:
  virtual bool IsServer() const { return FALSE; }
  virtual bool IsClient() const { return FALSE; }
  virtual bool IsOk() const     { return FALSE; }

  virtual bool Execute(CONNID id, const char* cmd);
  virtual bool Request(CONNID id, const char* cmd);

  int ForEachConnection(ConnectionFunction f, void* pJolly);
  
  bool HasConnections() const;
  TConnection* GetConnection(CONNID id) const;
  
  bool RemoveConnection(CONNID id);
  void RemoveAllConnections();

  TLanManager();
  virtual ~TLanManager();
};

class TLanServer : public TLanManager
{
  TString m_strName;

public:
  const TString& Name() const { return m_strName; }
  
  virtual bool IsServer() const { return TRUE; }

  virtual byte* GetBuffer(unsigned int dwSize) pure;
  byte* GetBufferSetString(const char* str);
  byte* GetBufferSetBool(bool ok);
  byte* GetBufferSetInteger(long n);
  
  TLanServer(const char* name) : m_strName(name) { }
  virtual ~TLanServer() { }
};

class TLanClient : public TLanManager
{
protected:
  virtual TConnection* OnQueryConnection(const char* service, const char* server) pure;

public:
  virtual bool IsClient() const { return TRUE; }
  
  CONNID QueryConnection(const char* service, const char* server = NULL);

  virtual bool Execute(CONNID id, const char* cmd);
  virtual bool Request(CONNID id, const char* cmd);
  virtual byte* GetBuffer(unsigned int& dwSize) = 0;
  virtual void ReleaseBuffer() = 0;

  bool RequestString(CONNID id, const char* cmd, TString& res);
  bool RequestInteger(CONNID id, const char* cmd, long& num);
  bool RequestBool(CONNID id, const char* cmd, bool& ok);
};

class TConnection : public TObject
{
  TLanManager* m_pManager;
  CONNID m_dwId;

protected:
  int ParseCommand(const char* cmd, TString_array& argv);
	void SetId(CONNID id) { m_dwId = id; } // Internal use only

public:
  CONNID Id() const { return m_dwId; }
  
  TLanManager& Manager() const { return *m_pManager; }
  TLanServer& Server() const;

  virtual bool Execute(const char* cmd);
  virtual bool Request(const char* cmd);

  bool ReturnBool(bool b) const { return Server().GetBufferSetBool(b) != NULL; }
  bool ReturnInteger(long n) const { return Server().GetBufferSetInteger(n) != NULL; }
  bool ReturnString(const TString& s) const { return Server().GetBufferSetString(s) != NULL; }

  TConnection(TLanManager* lm, CONNID id);
  virtual ~TConnection();
};

#endif