#if !defined (_CDEV_SERVER_H_)
#define _CDEV_SERVER_H_

#include "SignalManager.h"
#include "cdevServerTools.h"
#include "cdevMessage.h"
#include "cdevContextMap.h"
#include "cdevTagMap.h"
#include "ClientInfo.h"
#include "ServerInfo.h"
#include "cdevGenericServerTags.h"

// *****************************************************************************
// * class CLIPClientSession :
// * 
// *	This class also allows the server to associate certain data with a 
// *	specific client...
// *
// *	context:   This is a pointer to the most recently used context from the
// *               cdevContextMap.
// *****************************************************************************
class GENERIC_SERVER_API CLIPClientSession : public ClientSession
{
private:
	cdevData *context;

public:
	CLIPClientSession ( int SocketID, int ClientID, int LocalID )
		: ClientSession(SocketID, ClientID, LocalID),
		  context(NULL)
		{
		}
	virtual   ~CLIPClientSession ( void )           { }
	cdevData * getContext        ( void )           { return context; }
	void       setContext        ( cdevData * cxt ) { context = cxt; }
};


// *****************************************************************************
// * class CLIPSocketSession :
// * 
// *	This class allows the developer to associate additional information with
// *	a particular socket...
// *
// *	contextMap : a table of cdevData contexts that can be retrieved by index
// *
// *	tagMap     : the table for mapping cdevData tags from the remote system
// *                 to the tag table associated with this system.
// *****************************************************************************
class GENERIC_SERVER_API CLIPSocketSession : public SocketSession, public ClientInfoStruct
{
private:
	cdevContextMap contextMap;
	cdevTagMap     tagMap;
	
public:
	CLIPSocketSession                  ( int SocketID )
		: SocketSession ( SocketID )
		{
		}
	virtual         ~CLIPSocketSession ( void ) { }
	cdevContextMap & ContextMap        ( void ) { return contextMap; }
	cdevTagMap     & TagMap            ( void ) { return tagMap; }
};


// *****************************************************************************
// * cdevServer :
// *	This is the cdevServer class.  It is responsible for establishing a 
// *	listening socket, and then responding to all incoming and outgoing
// *	messages.
// *****************************************************************************
class GENERIC_SERVER_API cdevServer : public cdevSessionManager
{
public:
	typedef enum { SUCCESS = 0, 
	               UNINITIALIZED,
	               CANT_OPEN_SOCKET,
	               CANT_REGISTER_LISTENER,
	               CANT_REGISTER_SERVER,
	               CANT_REGISTER_TIMER
	             } ServerInitStatus;

protected:
	char                  * serverName;
	class ClientAcceptor  * acceptor;
	cdevNameServerManager * timer;
	ServerInitStatus        status;
	ServerInfo            * serverInfo;
			
public:
	static  cdevGenericServerTagDef tags;
	static  SignalManager           SigManager;
	static  sig_atomic_t            Finished;

	static  void               runServer    (void);
	
	cdevServer                              (char * DomainName, char * ServerName, unsigned short Port, double Rate);
	cdevServer                              (void);
	virtual                   ~cdevServer   (void);
	int                        startServer  (char * DomainName, char * ServerName, unsigned short Port, double Rate, int searchForPort=0);

	virtual void               registerClient   ( short localID );
	virtual void               unregisterClient ( short localID );

	virtual ClientSession *    newClientSession    ( int SocketID, int ClientID, int LocalID );
	virtual SocketSession *    newSocketSession    ( int SocketID );
	virtual void               deleteSocketSession ( SocketSession *socket );
	
	virtual int                dequeue      (cdevMessage * &message);
	void                       processLocal (cdevMessage * &message); 
	virtual cdevPacket *       decodePacket (cdevPacketBinary * input);
	virtual cdevPacket *       decodePacket (cdevMessage * message);
	virtual cdevPacketBinary * encodePacket (cdevPacket * input);
	virtual cdevPacketBinary * encodePacket (cdevMessage * message);
	virtual int                operational  (void) { return (status==0)?1:0; }
	virtual ServerInitStatus   getInitStatus(void) { return status; }
};

#endif  /* _CDEV_SERVER_H_ */
