#ifndef _CDEV_MESSAGE_H_
#define _CDEV_MESSAGE_H_ 1

#include <cdevData.h>
#include <cdevPacket.h>
#include <cdevMessageBinary.h>

class GENERIC_SERVER_API cdevMessage : public cdevPacket
{	
private:
	typedef union
		{
		unsigned char rawData;
		struct	{
			unsigned char saveDeviceList : 1;
			unsigned char saveMessage    : 1;
			unsigned char saveData       : 1;
			unsigned char saveContext    : 1;
			unsigned char saveTagMap     : 1;
			unsigned pad                 : 3;
			} value;
		} SaveTable;
		
	SaveTable  saveTbl; 

	short      clientID;
	unsigned   transIndex;
	unsigned   cancelTransIndex;
	unsigned   localDataIndex;
	unsigned   foreignDataIndex;
	unsigned   operationCode;
	int        completionCode;
	unsigned   deviceCount;
	char **    deviceList;
	char *     message;
	cdevData * data;
	cdevData * context;
	cdevData * tagMap;
	
public:
	enum { CDEV_PACKET_VERSION = cdevMessageBinary::CDEV_PACKET_VERSION };
	
	static cdevPacket *import( cdevPacketBinary & );

	cdevMessage              ( short      ClientID         = -1, 
	                           unsigned   TransIndex       = 0,
	                           unsigned   CancelTransIndex = 0,
	                           unsigned   LocalDataIndex   = 0,
	                           unsigned   ForeignDataIndex = 0,
	                           unsigned   OperationCode    = 0,
	                           int        CompletionCode   = 0,
	                           unsigned   DeviceCount      = 0,
	                           char **    DeviceList       = NULL,
	                           char *     Message          = NULL,
	                           cdevData * Data             = NULL,
	                           cdevData * Context          = NULL,
	                           cdevData * TagMap           = NULL);

	cdevMessage                    ( char * binary, size_t binaryLen );
	cdevMessage                    ( class cdevMessage & message );
	virtual         ~cdevMessage   ( void );
	virtual void     clear         ( void );
	virtual int      streamIn      ( char * binary, size_t binaryLen );
	virtual int      streamOut     ( char ** binary, size_t * binaryLen );
	virtual void     asciiDump     ( FILE * fp = stdout );

	virtual short    getVersion    ( void ) { return CDEV_PACKET_VERSION; }
	virtual short    getClientID   ( void ) { return clientID; }
	virtual unsigned getTransIndex ( void ) { return transIndex; }

	unsigned   getCancelTransIndex ( void ) { return cancelTransIndex; }
	unsigned   getLocalDataIndex   ( void ) { return localDataIndex; }
	unsigned   getForeignDataIndex ( void ) { return foreignDataIndex; }
	unsigned   getOperationCode    ( void ) { return operationCode; }
	int        getCompletionCode   ( void ) { return completionCode; }
	unsigned   getDeviceCount      ( void ) { return deviceCount; }
	char **    getDeviceList       ( void ) { return deviceList; }
	char *     getMessage          ( void ) { return message; }
	cdevData * getData             ( void ) { return data; }
	cdevData * getContext          ( void ) { return context; }
	cdevData * getTagMap           ( void ) { return tagMap; }

	virtual void setClientID  ( short ClientID )            { clientID = ClientID; }
	virtual void setTransIndex( unsigned TransIndex )       { transIndex = TransIndex; }

	void setCancelTransIndex  ( unsigned CancelTransIndex ) { cancelTransIndex = CancelTransIndex; }
	void setLocalDataIndex    ( unsigned LocalDataIndex )   { localDataIndex = LocalDataIndex; }
	void setForeignDataIndex  ( unsigned ForeignDataIndex ) { foreignDataIndex = ForeignDataIndex; }
	void setOperationCode     ( unsigned OperationCode )    { operationCode = OperationCode; }
	void setCompletionCode    ( int CompletionCode )        { completionCode = CompletionCode; }
	void setDeviceList        ( char ** DeviceList, int DeviceCount, int permanent = 0 )
		{
		if(deviceList!=NULL && !saveTbl.value.saveDeviceList)
			{
			for(int i=0; i<deviceCount; i++) delete deviceList[i];
			delete deviceList;
			}
		deviceList  = DeviceList;
		deviceCount = DeviceCount;
		saveTbl.value.saveDeviceList = permanent;
		}
	void setMessage          ( char * Message, int permanent = 0 )
		{
		if(message!=NULL && !saveTbl.value.saveMessage) delete message;
		message = Message;
		saveTbl.value.saveMessage = permanent;
		}
	void setData             ( cdevData * Data, int permanent = 0 )
		{
		if(data!=NULL && !saveTbl.value.saveData) delete data;
		data = Data;
		saveTbl.value.saveData = permanent;
		}
	void setContext          ( cdevData * Context, int permanent = 0 )
		{
		if(context!=NULL && !saveTbl.value.saveContext) delete context;
		context = Context;
		saveTbl.value.saveContext = permanent;
		}
	void setTagMap           ( cdevData * TagMap, int permanent = 0 )
		{
		if(tagMap!=NULL && !saveTbl.value.saveTagMap) delete tagMap;
		tagMap = TagMap;
		saveTbl.value.saveTagMap = permanent;
		}		
};

#endif /* _CDEV_MESSAGE_H_ */

