/*******************************************************************

Copyright (c) 2004 Open Mobile Alliance, Ltd.  All Rights Reserved.

This software is made available under the usage and distribution terms 
covered by the Common Public License 1.0 and by using this software you
are bound by the terms and conditions of the same.

EXCEPT AS EXPRESSLY SET FORTH IN THE COMMON PUBLIC LICENSE,
THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS, 
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, 
ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, 
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
   
Each recipient is solely responsible for determining the 
appropriateness of using and distributing this program and assumes 
all risks associated with its exercise of rights under the Common 
Public License, including but not limited to the risks and 
costs of program errors, compliance with applicable laws, 
damage to or loss of data, programs or equipment, and 
unavailability or interruption of operations.

********************************************************************/

#ifndef _SCTS_SESSION_H
#define _SCTS_SESSION_H
#include "SctsThread.h"
#include "SctsURI.h"
#include "SctsTransport.h"
#include "SctsMessage.h"
#include "SctsCommandElements.h"
#include "SctsErrorLog.h"
#include "SctsDevManDevice.h"
#include "stack"
#include "set"
#include "queue"
#include "list"

class SctsDMSession;
class SctsDMClientSession;
class SctsDMServerSession;
class SctsDMTestGroup;


/******************************************************************
UI Callbacks
******************************************************************/
/* 
These are UI defined callbacks which are called when objects are
created and destroyed. There is only one global variable (componentUIC)
which can be set using the 'sctsSetComponentUIC' function. Care must be
taken when handling this structure since it is not protected by a mutex.
Usually it is set when the UI starts and is not manipulated after that.
*/
typedef struct
{
	void (*addSession)(SctsDMSession *);
	void (*removeSession)(SctsDMSession *);
	void (*addClientDevice)(SctsDMClientDevice *);
	void (*addServerDevice)(SctsDMServerDevice *);
	void (*removeClientDevice)(SctsDMClientDevice *);
	void (*removeServerDevice)(SctsDMServerDevice *);
	int (*interactionAlert)(char *deviceID,int alertCode,std::list<char *>&items,int maxDT,int minDT,int maxLen,char *dr,char et,char dt);
} SctsComponentUICallbacks;
void sctsSetComponentUIC(SctsComponentUICallbacks *uic);
extern SctsComponentUICallbacks componentUIC;
/******************************************************************/

#ifdef __SCTS_USING_RTK__
#include "wsm.h"

Ret_t sctsRTKHandleAddCmd(InstanceID_t id,VoidPtr_t pSession,SmlAddPtr_t pCmd);
Ret_t sctsRTKHandleAlertCmd(InstanceID_t id,VoidPtr_t pSession,SmlAlertPtr_t pCmd);
Ret_t sctsRTKHandleCopyCmd(InstanceID_t id,VoidPtr_t pSession,SmlCopyPtr_t pCmd);
Ret_t sctsRTKHandleDeleteCmd(InstanceID_t id,VoidPtr_t pSession,SmlDeletePtr_t pCmd);
Ret_t sctsRTKHandleExecCmd(InstanceID_t id,VoidPtr_t pSession,SmlExecPtr_t pCmd);
Ret_t sctsRTKHandleGetCmd(InstanceID_t id,VoidPtr_t pSession,SmlGetPtr_t pCmd);
Ret_t sctsRTKHandlePutCmd(InstanceID_t id,VoidPtr_t pSession,SmlPutPtr_t pCmd);
Ret_t sctsRTKHandleMapCmd(InstanceID_t id,VoidPtr_t pSession,SmlMapPtr_t pCmd);
Ret_t sctsRTKHandleResultsCmd(InstanceID_t id,VoidPtr_t pSession,SmlResultsPtr_t pCmd);
Ret_t sctsRTKHandleSearchCmd(InstanceID_t id,VoidPtr_t pSession,SmlSearchPtr_t pCmd);
Ret_t sctsRTKHandleStatusCmd(InstanceID_t id,VoidPtr_t pSession,SmlStatusPtr_t pCmd);
Ret_t sctsRTKHandleReplaceCmd(InstanceID_t id,VoidPtr_t pSession,SmlReplacePtr_t pCmd);
Ret_t sctsRTKHandleStartMessage(InstanceID_t id,VoidPtr_t pSession,SmlSyncHdrPtr_t pCmd);
Ret_t sctsRTKHandleEndMessage(InstanceID_t id,VoidPtr_t pSession,Boolean_t final);
Ret_t sctsRTKHandleStartSync(InstanceID_t id,VoidPtr_t pSession,SmlSyncPtr_t pCmd);
Ret_t sctsRTKHandleEndSync(InstanceID_t id,VoidPtr_t pSession);
Ret_t sctsRTKHandleStartAtomic(InstanceID_t id,VoidPtr_t pSession,SmlAtomicPtr_t pCmd);
Ret_t sctsRTKHandleEndAtomic (InstanceID_t id,VoidPtr_t pSession);
Ret_t sctsRTKHandleStartSequence(InstanceID_t id,VoidPtr_t pSession,SmlSequencePtr_t pCmd);
Ret_t sctsRTKHandleEndSequence (InstanceID_t id,VoidPtr_t pSession);

#endif


/******************************************************************
DM Session Classes
******************************************************************/

#ifdef __SCTS_USING_SCTS__
class SctsTestGroup;
#endif
class SctsDMSession;
class SctsDMClientSession;
class SctsDMServerSession;

/*************************************************************
Enumerated Data Type Definitions
**************************************************************/

typedef enum
{
	PROCESS_ERR_NONE=0,
	PROCESS_ERR_OK,
	PROCESS_ERR_STOP,
} SctsSessionProcessError;

/*************************************************************
SctsDMResults Class 
**************************************************************/

class SctsDMResults
{
public:
	char *cmdRef;
	char *type;
	char *source;
	int	 msgRef;
	SctsDMNodeFormat format;
	SctsDMNodeProp prop;	
	SctsPcdata *pcData;
	SctsDMResults();
	~SctsDMResults();
};

//Introduced to fix some bugs..
	
typedef struct 
{
	void* pParam1;
	void* pParam2;
	void* pFutureParam; //The remaining any stuff pack it here....

}PARAMPKT,*PPARAMPKT;

/*************************************************************
SctsDMSession Class 
**************************************************************/

class SctsDMSession : public SctsThread
{
public:
	/* Data */
	void *uiData;
	void *uiCallbackData;
	void (*uiCallback)(void *data,SctsCommand *command,int flag,bool build);
	void *SetUICallback(void *_uiCallbackData,void (*_uiCallback)(void *data,SctsCommand *command,int flag,bool build))
	{
		void *_temp=uiCallbackData;
		uiCallbackData=_uiCallbackData;
		uiCallback=_uiCallback;
		return _temp;
	}
	SctsSessionProcessError processError;
	SctsStatus *nextSyncHdrStatus;
	int recvSyncHdrStatus;
	int sentSyncHdrStatus;
	bool recvdFinal;
	bool messageNoResp;
	/* V1.1.1 */
	bool supportsLrgObj;
	int sourcePkgCount;
	int targetPkgCount;
	char *sessionID;
	/* V1.1.1 changed int to unsigned int */
	unsigned int currentCmdID;
	unsigned int currentMsgID;
	unsigned int processMsgID;
	int itemsPerCommand;
	bool chalForHMAC;
	SctsSyncMLProto proto;
	SctsErrorLog *errorLog;
	SctsMessage *outgoingMessage;
	SctsDMSessionType sessionType;
	/* Postponement of status discrepency */
	std::deque<SctsMessage *> messageQueue;
	int messageQueueID;
	SctsEncoding encoding;
	SctsTransport *transport;
	SctsDMDevice *tempDevice;
	SctsAuth *inAuth;
	SctsAuth *outAuth;
	
	char *userID;
	char *password;	
	SctsSessionContext sessionContext;
#ifdef __SCTS_USING_SCTS__
	SctsDMTestGroup *testGroup;
#endif
	/* WBXML converter */
	SctsSessionContext wbxmlConverterContext;
	bool wbxmlConverting;
	FILE *logFile;
	FILE *logFileInf;
	char logFileName[200];

	/* Process Stack */
	typedef struct
	{
		SctsCommandType type;
		int status;
	} ProcessStackCmd;
	std::stack<ProcessStackCmd *> processStack;

	/* Large obect delivery */
	int largeObjectCmdSize;
	int largeObjectSize;
	int largeObjectBufferSize;
	int largeObjectBufferUsedSize;
	int largeObjectMsgRef;
	char *largeObjectCmdRef;
	char *largeObjectBuffer;
	char *largeObjectTURI;
	char *largeObjectSURI;
	char *largeObjectType;
	char *largeObjectFormat;
	SctsCommandType largeObjectCmd;
	SctsDMCommand *largeObjectCommand;
	bool LargeObjectRecvChunk(bool firstChunk,int &statusCode,SctsCommandType cmdType,SctsItem &item,SctsMeta &meta);
	bool LargeObjectSendChunk();
	void LargeObjectSendAlert();
	void LargeObjectClear();
	int largeObjectAlerts;

	/* Methods */
	void (*CallBack)(SctsDMSession *);
	virtual SctsSyncHdr *BuildSyncHdr()=0;
	bool HandleStatusRefs(SctsStatus& cmd,SctsItemList& itemList,bool& multipleStatus);
	void CreateErrorNode(SctsCommand&);
	bool RecvMessage();
	bool SendMessage();
	virtual bool IsServerSession()=0;
	bool IsSuccessful() {return processError==PROCESS_ERR_NONE;}
	void IsSuccessful(bool successful) {successful?processError=PROCESS_ERR_NONE:processError=PROCESS_ERR_STOP;}

	/* Constructor & Destructor*/
	SctsDMSession(SctsEncoding _encoding,void (*_CallBack)(SctsDMSession *)=0);
	virtual ~SctsDMSession();
	virtual SctsDMDevice *GetDevice(){return 0;}
	
	virtual void ProcessStateInitiateMessage() {}
	virtual void ProcessStateManageMessage() {}
	
	virtual void BuildStateInitiateMessage()=0;
	virtual void BuildStateManageMessage()=0;
	
	virtual void HandleStartMessage(SctsSyncHdr& cmd)=0;
	virtual void HandleEndMessage(bool final)=0;
	virtual void HandleStartSync(SctsSync& cmd)=0;
	virtual void HandleEndSync()=0;
	virtual void HandleStartAtomic(SctsAtomic& cmd)=0;
	virtual void HandleEndAtomic()=0;
	virtual void HandleStartSequence(SctsSequence& cmd)=0;
	virtual void HandleEndSequence()=0;
	virtual void HandleAdd(SctsAdd& cmd)=0;
	virtual void HandleDelete(SctsDelete& cmd)=0;
	virtual void HandleReplace(SctsReplace& cmd)=0;
	virtual void HandleCopy(SctsCopy& cmd)=0;
	virtual void HandlePut(SctsPut& cmd)=0;
	virtual void HandleGet(SctsGet& cmd)=0;
	virtual void HandleSearch(SctsSearch& cmd)=0;
	virtual void HandleResults(SctsResults& cmd)=0;
	virtual void HandleMap(SctsMap& cmd)=0;
	virtual void HandleStatus(SctsStatus& cmd)=0;
	virtual void HandleExec(SctsExec& cmd)=0;
	virtual void HandleAlert(SctsAlert& cmd)=0;
};

/*************************************************************
SctsDMClientSession Class 
**************************************************************/

class SctsStatusRef
{
public:
	int status;
	int msgID;
	char *cmdID;
	SctsDMNodeProp prop;
	void *data;
	SctsStatusRef();
	~SctsStatusRef();
};

class SctsDMClientSession : public SctsDMSession 
{
public:
	/* Flag to control OBEX Client transport */
	static bool useOBEXIR;
	/* Data */
	long maxMsgSize;
	bool authenticateAllMsgs;
	bool sentDevInfo;
	bool sentSessionInitiationAlert;
	bool retryAuth;
	SctsDMClientDevice *device;
	std::deque<SctsDMResults *> pendingResults;
	SctsDMResults *lastPendingResults;
	std::stack<SctsDMCommand *> atomicStack; 
	SctsTree<SctsCommand *>::Item *lastAtomicStatus;
	/* V1.1.1 */
	std::list<SctsCommand *> pendingStatus;
	int alertCode;
	
	std::map<SctsCommandType,std::list<SctsStatusRef *> > sentStatusRefs;
	/* Methods */
	SctsDMDevice *GetDevice() {return (SctsDMDevice *)device;}	
	bool IsServerSession() {return false;}
	
	/* Thread Methods */
	int Exit();
	int Run();	
	/* Constructor & Destructor */
	SctsDMClientSession(SctsDMClientDevice *_device,SctsEncoding _encoding,void (*_CallBack)(SctsDMSession *)=0,bool _authenticateAllMsgs=false);
	~SctsDMClientSession();	

	SctsSyncHdr *BuildSyncHdr();
	void BuildStateInitiateMessage();
	void BuildStateManageMessage();
	void BuildResults(SctsDMResults *results,SctsDMNode *node);

	void HandleStartMessage(SctsSyncHdr& cmd);
	void HandleEndMessage(bool final);
	void HandleStartSync(SctsSync& cmd);
	void HandleEndSync();
	void HandleStartAtomic(SctsAtomic& cmd);
	void HandleEndAtomic();
	void HandleStartSequence(SctsSequence& cmd);
	void HandleEndSequence();
	void HandleAdd(SctsAdd& cmd);
	void HandleDelete(SctsDelete& cmd);
	void HandleReplace(SctsReplace& cmd);
	void HandleCopy(SctsCopy& cmd);
	void HandlePut(SctsPut& cmd);
	void HandleGet(SctsGet& cmd);
	void HandleSearch(SctsSearch& cmd);
	void HandleResults(SctsResults& cmd);
	void HandleMap(SctsMap& cmd);
	void HandleStatus(SctsStatus& cmd);
	void HandleExec(SctsExec& cmd);
	void HandleAlert(SctsAlert& cmd);	

private:
    unsigned int getTNDSPropSet;
    SctsDMNode *subTreeRoot;
    int getRight;
    SmlSubTreePtr_t getSubTree;
    SmlSubTreeNodePtr_t getSubTreeNode;
    bool sendGenericAlert;

    int addDMTree(SctsDMClientDevice *device, char *target, SmlSubTreePtr_t pMgmtTree, SctsDMCommand **command=0);
	int replaceDMTree(SctsDMClientDevice *device, char *target, SmlSubTreePtr_t pMgmtTree, SctsDMCommand **command=0);
	int isProperty(const char *propString, const char *property);
	int isPropertySet(const char *propString, const char *property);
    void setGetTNDSProperty(SctsGetTNDSProperty property, int value);
    int isGetTNDSProperty(SctsGetTNDSProperty property);
};

/*************************************************************
SctsDMServerSession Class 
**************************************************************/

class SctsDMServerSession : public SctsDMSession 
{
public:
	/* Data */
	long maxMsgSize;
	bool authenticateAllMsgs;
	bool receivedDevInfo;
	bool clientInitiatedAlert;
	bool serverInitiatedAlert;
	bool receivedSessionAbortAlert;
	char *sourceLocURI;
	char *targetLocURI;
	SctsDMServerDevice *device;
    bool authRetry;
    static const char *discoveryTempPath;
	static SctsMutex discoveryAccountLock;
	static char *discoveryName;
	static char *discoveryContact;
	static char *discoveryCompany;
	static char *discoveryDMAccPath;
	static char *discoveryDMAccName;
	static SctsDMTree *discoveryAccount;
	/* Methods */

	SctsDMDevice *GetDevice() {return (SctsDMDevice *)device;}
	bool IsServerSession(){ return true;}
	
	/* Constructor & Destructor */
	SctsDMServerSession(SctsServerTransport *_transport,SctsEncoding _encoding,void (*_CallBack)(SctsDMSession *)=0,bool _authenticateAllMsgs=false);
	~SctsDMServerSession();
	/* Thread Methods */
	int Exit();
	int Run();

	void BuildStateInitiateMessage();
	void BuildStateManageMessage();
	SctsSyncHdr *BuildSyncHdr();

	void HandleStartMessage(SctsSyncHdr& cmd);
	void HandleEndMessage(bool final);
	void HandleStartSync(SctsSync& cmd);
	void HandleEndSync();
	void HandleStartAtomic(SctsAtomic& cmd);
	void HandleEndAtomic();
	void HandleStartSequence(SctsSequence& cmd);
	void HandleEndSequence();
	void HandleAdd(SctsAdd& cmd);
	void HandleDelete(SctsDelete& cmd);
	void HandleReplace(SctsReplace& cmd);
	void HandleCopy(SctsCopy& cmd);
	void HandlePut(SctsPut& cmd);
	void HandleGet(SctsGet& cmd);
	void HandleSearch(SctsSearch& cmd);
	void HandleResults(SctsResults& cmd);
	void HandleMap(SctsMap& cmd);
	void HandleStatus(SctsStatus& cmd);
	void HandleExec(SctsExec& cmd);
	void HandleAlert(SctsAlert& cmd);
};

#endif
