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

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_DMDEVICE_H
#define _SCTS_DMDEVICE_H

#include "SctsAuth.h"
#include "SctsDevManT&D.h"
#include "SctsDevManTestEngine.h"
#include "map"
#include "string"
#include "deque"

class SctsDMDevice;
class SctsDMClientDevice;
class SctsDMServerDevice;

typedef enum
{
	DMSESSION_NORMAL=0,
	DMSESSION_TEST,
	DMSESSION_BOOTSTRAP,
	DMSESSION_DISCOVER
} SctsDMSessionType;


/*************************************************************
SctsDMGenericAlert Class 
**************************************************************/

class SctsDMGenericAlert
{
public:
	char *type;
	char *format;
	char *source;
    char *correlator;
    char *mark;
	char *data;
	SctsDMGenericAlert();
	~SctsDMGenericAlert();
};

/******************************************************************
SctsDMDevice Class
******************************************************************/

/* Client's outgoing auth is stored in its tree */

class SctsDMDevice : public SctsMutex
{
public:
	char *serverID; 
	char *dmAccPath;
	char *productName;
	char *productContact;
	char *productCompany;

    struct MulDynAccItem
    {
        MulDynAccItem() {}
        MulDynAccItem(const std::string& _accName,
                      const std::string& _accPath,
                      const std::string& _subAppAddr,
                      const std::string& _subPort,
                      const std::string& _subAppAuthClient,
                      const std::string& _subAppAuthServer,
                      const std::string& _subToConRef)
            : accName(_accName), accPath(_accPath), subAppAddr(_subAppAddr), 
              subPort(_subPort), subAppAuthClient(_subAppAuthClient), subAppAuthServer(_subAppAuthServer),
              subToConRef(_subToConRef)
        {
            convURI(subAppAddr);
            convURI(subPort);
            convURI(subAppAuthClient);
            convURI(subAppAuthServer);
            convURI(subToConRef);
        }
        MulDynAccItem(const MulDynAccItem& oth)
            : accName(oth.accName), accPath(oth.accPath), subAppAddr(oth.subAppAddr), 
              subPort(oth.subPort), subAppAuthClient(oth.subAppAuthClient), subAppAuthServer(oth.subAppAuthServer),
              subToConRef(oth.subToConRef)
        {}
        std::string accName;
        std::string accPath;
        std::string subAppAddr;
        std::string subPort;
        std::string subAppAuthClient;
        std::string subAppAuthServer;
        std::string subToConRef;

        void convURI(std::string& inStr)
        {
            if (inStr.length() >2 && inStr[0] == '.' && inStr[1] == '/')
                inStr = inStr.substr(2);
        }
    };
    typedef std::map<std::string,MulDynAccItem> MDAccType;
    MDAccType accounts;

    void *uiData;
	SctsDMNode *accountNode;
	SctsDMSessionType sessionType;
	SctsDMTester *tester;
	static char *GetSctsServerID() {return "Scts";}
	static std::map<std::string,SctsDMServerDevice *> serverDevices;
	static std::map<std::string,SctsDMClientDevice *> clientDevices;
	static SctsDMServerDevice *AddServerDevice(char *serverID,char *dmAccPath,char *userID,char *name=0,char *contact=0,char *company=0);
	static SctsDMClientDevice *AddClientDevice(char *devID,char *dmAccPath,long maxObjSize,SctsEncoding encoding,char *name=0,char *contact=0,char *company=0);
	static void RemoveDevice(SctsDMDevice *device);
	static SctsDMServerDevice *GetServerDevice(char *userID);
	static SctsDMClientDevice *GetClientDevice(char *devID);
	static void LoadAll(FILE *fp);
	static void SaveAll(FILE *fp);
	static void RemoveAll();
	
	virtual bool IsServerDevice() {return false;}
	
	char *GetUserID();
	char *GetPassword(bool in);
	unsigned char *GetNonce(bool in,unsigned int& size);
	virtual SctsAuthType GetAuthType(bool in)=0;
	void SetUserID(char *userID);
	void SetPassword(bool in,char *password);
	void SetNonce(bool in,unsigned char *_nonce,unsigned int size);
	virtual void SetAuthType(bool in,SctsAuthType authType)=0;
	
	SctsDMDevice(FILE *fp);
	void Save(FILE *fp);
	void SetSessionType(SctsDMSessionType _sessionType) {sessionType=_sessionType;}
	
	SctsDMDevice(char *name=0,char *contact=0,char *company=0);
protected:
	virtual ~SctsDMDevice();
};

class SctsDMClientDevice : public SctsDMDevice, public SctsDMTree
{
private:
	/* Mapping of account names to authentication types */
	std::map<std::string,SctsAuthType> inAuthTypes;
	std::map<std::string,SctsAuthType> outAuthTypes;
	static SctsDMClientDevice *notificationDevice;
	static void (*notificationCallback)(SctsDMSession *);
	static SctsMutex notificationMutex;
public:
	static void setNotificationDeviceParams(SctsDMClientDevice *device,void (*_CallBack)(SctsDMSession *))
	{
		notificationMutex.Lock();
		notificationDevice=device;
		notificationCallback=_CallBack;
		notificationMutex.Unlock();
	}

	static SctsDMClientDevice *getNotificationDevice()
	{
		SctsDMClientDevice *device;
		notificationMutex.Lock();
		device=notificationDevice;
		notificationMutex.Unlock();
		return device;
	}

	static void *getNotificationCallback()
	{
		void (*_CallBack)(SctsDMSession *);
		notificationMutex.Lock();
		_CallBack=notificationCallback;
		notificationMutex.Unlock();
		return _CallBack;
	}

	SctsSyncMLProto proto;
	SctsEncoding encoding;
	unsigned int lastSessionID;
	char *devID;
	long maxMsgSize;
	long maxObjSize;
	void SetAuthType(bool in,SctsAuthType authType);
	SctsAuthType GetAuthType(bool in);
	
	void Save(FILE *fp);	
	SctsDMClientDevice(char *_devID,char *_dmAccPath,long _maxObjSize,SctsEncoding _encoding,char *name=0,char *contact=0,char *company=0);
	SctsDMClientDevice(FILE *fp);
    bool IsDevice() {return true;}

    /*
     * Change to support TNDS. 
     */
    int ReplaceDMNodePropTNDS(SctsDMNode *node,char *serverID,SctsDMNodeProp prop,char *propVal,SctsDMCommand **command=0);
    /*
     * Change to support Generic Alert. 
     */
    std::deque<SctsDMGenericAlert *> pendingGenericAlerts;
    SctsDMGenericAlert *lastPendingGenericAlerts;

private:
	~SctsDMClientDevice();
};

class SctsDMServerDevice : public SctsDMDevice, public SctsDMServerTree
{
private:
	SctsAuthType inAuthType;
	SctsAuthType outAuthType;
public:
	char *userID;
	bool IsServerDevice() {return true;}
	void SetAuthType(bool in,SctsAuthType authType);
	SctsAuthType GetAuthType(bool in);

	void Save(FILE *fp);
	SctsDMServerDevice(char *_serverID,char *_dmAccPath,char *name=0,char *contact=0,char *company=0,char *testNode=".");	
	SctsDMServerDevice(FILE *fp);
    bool IsDevice() {return true;}
    /*
     * Change to support Generic Alert. 
     */
    std::deque<SctsDMGenericAlert *> pendingGenericAlerts;
    SctsDMGenericAlert *lastPendingGenericAlerts;

private:
	~SctsDMServerDevice();	
};

#endif