#ifndef __NETUTILS_H__
#define __NETUTILS_H__  

#ifdef NO_MFC   
#define STRICT
#include <windows.h>
#include "assoc.h"
#endif

class TConnection;

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

class TLanManager : public CObject
{                
#ifdef NO_MFC
  TAssoc_array m_mapConn;
#else
  CMap<DWORD, DWORD, TConnection*, TConnection*> m_mapConn;
#endif  

protected:
  DWORD AddConnection(TConnection* pConn);

  virtual TConnection* OnCreateConnection(DWORD id);                           
  virtual BOOL OnRemoveConnection(DWORD id);

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

  virtual BOOL Execute(DWORD id, const char* cmd);
  virtual BOOL Request(DWORD id, const char* cmd);

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

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

class TLanServer : public TLanManager
{
  CString m_strName;

public:
  const CString& Name() const { return m_strName; }
  
  virtual BOOL IsServer() const { return TRUE; }

  virtual BYTE* GetBuffer(DWORD dwSize) = 0;
  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) = 0;
public:
    virtual BOOL IsClient() const { return TRUE; }
  
  DWORD QueryConnection(const char* service, 
                  const char* server = NULL);

  virtual BOOL Execute(DWORD id, const char* cmd);
  virtual BOOL Request(DWORD id, const char* cmd);
  virtual BYTE* GetBuffer(DWORD& dwSize) = 0;
  virtual void ReleaseBuffer() = 0;

  BOOL RequestString(DWORD id, const char* cmd, CString& res);
  BOOL RequestInteger(DWORD id, const char* cmd, long& num);
  BOOL RequestBool(DWORD id, const char* cmd, BOOL& ok);
};

class TConnection : public CObject
{
  TLanManager* m_pManager;
  DWORD m_dwId;

protected:
  int ParseCommand(const char* cmd, CStringArray& argv);

public:
  DWORD 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(int b) const { return Server().GetBufferSetBool(b) != NULL; }
  BOOL ReturnInteger(long n) const { return Server().GetBufferSetInteger(n) != NULL; }
  BOOL ReturnString(const CString& s) const { return Server().GetBufferSetString(s) != NULL; }

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

enum OsType { WINDOWS_31, WINDOWS_95, WINDOWS_NT };
OsType GetOsType();

#endif