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

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 _ISYNC_DEVMAN_TREE_H
#define _ISYNC_DEVMAN_TREE_H

#include "SctsPlatformLib.h"
#include "SctsCommandElements.h"
#include "SctsErrorLog.h"
#include "string.h"
#include "list"
#include "vector"
#include "deque"

#define SIDX (char *)-1

typedef enum
{
	DMPROP_ACL=0,
	DMPROP_FORMAT,
	DMPROP_NAME,
	DMPROP_TITLE,
	DMPROP_TIMESTAMP,
	DMPROP_MIMETYPE,
	DMPROP_SIZE,
	DMPROP_VERSION,
	DMPROP_STRUCT,
	DMPROP_STRUCTDATA,
    /*
     * Change to support TNDS. 
     */
	DMPROP_TNDS,
	DMPROP_TNDS_STARTNODE,
	DMPROP_TNDS_ENDNODE,
	DMPROP_NONE
} SctsDMNodeProp;

typedef enum
{
	DMFORMAT_CHR=0,
	DMFORMAT_NODE,
	DMFORMAT_NULL,
	DMFORMAT_BIN,
	DMFORMAT_BOOL,
	DMFORMAT_B64,
	DMFORMAT_INT,
	DMFORMAT_XML,
    DMFORMAT_DATE,
    DMFORMAT_TIME,
    DMFORMAT_FLOAT,
	DMFORMAT_NONE
} SctsDMNodeFormat;


/*
 * Change to support TNDS. 
 */
extern char SctsDMFormatString[12][6];
extern char SctsDMNodePropertyString[12][11];

typedef enum
{
    GET_TNDS_VALUE = 0,
    GET_TNDS_ACL,
    GET_TNDS_FORMAT,
    GET_TNDS_VERNO,
    GET_TNDS_SIZE,
    GET_TNDS_TITLE
} SctsGetTNDSProperty;
extern char SctsGetTNDSPropertyString[7][9];
/* The Tree's Node Class */
class SctsDMNode
{
public:
	/* Variables */
	SctsDMNode *parent;
	SctsDMNode *child;
	SctsDMNode *next;
	SctsDMNode *prev;
	char *acl;
	SctsDMNodeFormat format;
	char *name;
	char *title;
	char *timeStamp;
	char *mimeType;
	unsigned int size;
	unsigned int version;
	void *data;
	bool permanent;
	bool markedForDelete;
	void *uiData;

	/* Implementation */
	bool VerifyACLSyntax(char *_acl);
	bool VerifyACL(char *serverID,SctsCommandType command, bool checkParent=true,bool*grantable=0);
	char *GetACL(bool checkParent=true);
	bool IsParent(SctsDMNode *parent);
	void GetPcdata(SctsPcdata& pcData,SctsDMNodeFormat& _format,SctsEncoding encoding);
	SctsDMNode(SctsDMNode *_node);
	SctsDMNode(char *_name,SctsDMNodeFormat _format,bool _permanent,char *_acl,void *_data,char *_mimeType,unsigned int _size);
	~SctsDMNode();
	SctsDMNode(FILE *fp);
	void Save(FILE *fp);	
};

class SctsDMCommand
{
public:
    class SctsDMCommandSpecific
    {
    public:
        std::string correlator;
        std::string tndsFields;
        std::string copyFrom;
        SctsDMCommandSpecific() : correlator(""), tndsFields(""), copyFrom("")
        {
        }
    };
    SctsDMCommandSpecific cmdSpecific;
	char *cmdRef;
	int msgRef;
	unsigned int size;
	void *data;
	bool reusable;
	int status;
	SctsDMNode *nodeRef;
	SctsDMNodeProp prop;
	SctsCommandType command;
	void RollBack();
	void RollBack(std::list<SctsDMCommand *>& cmdList,std::list<SctsDMCommand *>::iterator _cmdListIt);
	SctsDMCommand(SctsCommandType _command,SctsDMNode *_nodeRef=0,SctsDMNodeProp _prop=DMPROP_NONE,bool _reuseable=false,SctsDMCommandSpecific *_specific=0);
	~SctsDMCommand();
	SctsDMCommand(FILE *fp);
	void Save(FILE *fp);	
};

class SctsDMTree
{
public:
	/* The root object of the tree */
	SctsDMNode *root;
	void *uiCallbackData;
	void (*uiCallback)(SctsDMTree *,SctsDMNode *,SctsCommandType);
	
	SctsDMNode *FindDMNode(char *nodeName,SctsDMNode *startNode=0);
	char *GetPath(SctsDMNode *node,char *path=0,SctsDMNode *rootNode=0);
	void RemoveServerID(char *serverID);
	virtual int GetDMNode(SctsDMNode *node,char *serverID,SctsDMNodeProp prop,SctsDMCommand **command=0);
	virtual int ReplaceDMNodeProp(SctsDMNode *node,char *serverID,SctsDMNodeProp prop,char *propVal,SctsDMCommand **command=0);
	virtual int ReplaceDMNodeData(SctsDMNode *node,char *serverID,void *data,unsigned int size,char *format,char *mimeType,SctsDMCommand **command=0);
	virtual int DeleteDMNode(SctsDMNode *node,char *serverID,SctsDMCommand **command=0);
	virtual int AddDMNode(char *nodeName,char *serverID,char *_format,bool _permanent,void *_data,char *_mimeType,unsigned int _size,SctsDMNode **node=0,SctsDMCommand **command=0);
	virtual int GetDMNode(char *nodeName,char *serverID,SctsDMNodeProp prop,SctsDMCommand **command=0);
	virtual int GetDMNodeTNDS(char *nodeName,char *serverID,char *fields=0,SctsDMCommand **command=0);
	virtual int GetDMNodeTNDS(SctsDMNode *node,char *serverID,char *fields,SctsDMCommand **command=0);
	virtual int ReplaceDMNodeProp(char *nodeName,char *serverID,SctsDMNodeProp prop,char *propVal,SctsDMCommand **command=0);
	virtual int ReplaceDMNodeData(char *nodeName,char *serverID,void *data,unsigned int size,char *format,char *mimeType,SctsDMCommand **command=0);
	virtual int DeleteDMNode(char *nodeName,char *serverID,SctsDMCommand **command=0);
	virtual int ExecDMNode(char *nodeName,char *serverID,SctsDMCommand **command=0);
	virtual int ExecDMNode(SctsDMNode *node,char *serverID,SctsDMCommand **command=0);
	virtual int CopyDMNode(char *nodeNameFrom,char *nodeNameTo,char *serverID,SctsDMCommand **command=0);
	virtual int CopyDMNode(SctsDMNode *nodeFrom,char *nodeNameTo,char *serverID,SctsDMCommand **command=0);
	virtual bool IsServerTree() {return false;}
    virtual bool IsDevice() {return false;}
	/* Constructor  & Destructor*/
	SctsDMTree(char *_acl) { root = new SctsDMNode(".",DMFORMAT_NODE,true,_acl,0,0,0);uiCallbackData=0;uiCallback=0;}	
	SctsDMTree(){ root = new SctsDMNode(".",DMFORMAT_NODE,true,"Add=*&Replace=*&Get=*&Delete=*",0,0,0);uiCallbackData=0;uiCallback=0;}
	virtual ~SctsDMTree() { if (root) delete root; }
	virtual void Load(FILE *fp);
	virtual void Save(FILE *fp);	

    typedef std::vector<SctsDMNode *> SctsDMNodePtrVec;
    const SctsDMNodePtrVec FindAnyDMNode(char *nodeName,SctsDMNode *startNode=0);
	int AddFullDMNode(char *nodeName,char *serverID,char *_format,bool _permanent,void *_data,char *_mimeType,unsigned int _size,SctsDMNode **node=0,SctsDMCommand **command=0);
	virtual int GetDMNodeTNDS(char *nodeName,char *serverID,char *props,SctsPcdata& pcData,SctsEncoding encoding,SctsDMCommand **command=0);
	virtual int GetDMNodeTNDS(SctsDMNode *node,char *serverID,char *props,SctsPcdata& pcData,SctsEncoding encoding,SctsDMCommand **command=0);
};


class SctsDMServerTree :public SctsDMTree
{
public:
	std::list<SctsDMCommand *> cmdList;
	void InsertCommand(SctsDMCommand *item);
	int GetDMNode(SctsDMNode *node,char *serverID,SctsDMNodeProp prop,SctsDMCommand **command=0);
	int ReplaceDMNodeProp(SctsDMNode *node,char *serverID,SctsDMNodeProp prop,char *propVal,SctsDMCommand **command=0);
	int ReplaceDMNodeData(SctsDMNode *node,char *serverID,void *data,unsigned int size,char *format,char *mimeType,SctsDMCommand **command=0);
	int DeleteDMNode(SctsDMNode *node,char *serverID,SctsDMCommand **command=0);
	int AddDMNode(char *nodeName,char *serverID,char *_format,bool _permanent,void *_data,char *_mimeType,unsigned int _size,SctsDMNode **node=0,SctsDMCommand **command=0);
	int GetDMNode(char *nodeName,char *serverID,SctsDMNodeProp prop,SctsDMCommand **command=0);
	int ReplaceDMNodeProp(char *nodeName,char *serverID,SctsDMNodeProp prop,char *propVal,SctsDMCommand **command=0);
	int ReplaceDMNodeData(char *nodeName,char *serverID,void *data,unsigned int size,char *format,char *mimeType,SctsDMCommand **command=0);
	int DeleteDMNode(char *nodeName,char *serverID,SctsDMCommand **command=0);
	int ExecDMNode(char *nodeName,char *serverID,SctsDMCommand **command=0);
	int ExecDMNode(SctsDMNode *node,char *serverID,SctsDMCommand **command=0);
	virtual int CopyDMNode(char *nodeNameFrom,char *nodeNameTo,char *serverID,SctsDMCommand **command=0);
	virtual int CopyDMNode(SctsDMNode *nodeFrom,char *nodeNameTo,char *serverID,SctsDMCommand **command=0);
	bool IsServerTree() {return true;}
	
	/* Flag to prevent sending of management commands if it is a new device */
	bool newDevice;
	bool GrantACLRight(SctsDMNode *node,char *serverID,SctsCommandType command,bool lastNode=true,bool insert=false);
	SctsDMServerTree(char *_acl): SctsDMTree(_acl) {newDevice=true;}
	SctsDMServerTree(): SctsDMTree() {newDevice=true;}
	~SctsDMServerTree();	
	void Load(FILE *fp);
	void Save(FILE *fp);	
};

class SctsDMTNDSTree
{
public:
    SctsDMTNDSTree(const char *_format, const char *_mime, char *_tndsData, int _dataSize);
    //bool ConstructTree(SctsDMNode *baseNode);
    enum
    {
        VAL_OK = 0,
        NVAL_TYPE_FORMAT,
        NVAL_STRUCTURE,
        NVAL_CONTENT,
        NVAL_ENOUGH_INFO
    };
    int IsValid(char *tndsInfoFields);
private:
    std::string format;
    std::string mime;
    char *tndsData;
    int dataSize;
    int errCode;
    SmlSubTreePtr_t pMgmtTree;

    void SetGetTNDSProperty(SctsGetTNDSProperty property, int value, unsigned int& tndsPropSet)
    {
        if (value==1)
        {
            tndsPropSet |= (1u << property);
        }
        else if (value==-1)
        {
            tndsPropSet &= ~(1u << property);
        }
    }

    int IsGetTNDSProperty(SctsGetTNDSProperty property, unsigned int tndsPropSet)
    {
        unsigned int val = 0;
        val = 1u << property;
        val &= tndsPropSet;
        return val;
    }

    int CheckTndsInfo(SmlSubTreeNodePtr_t node, unsigned int tndsPropSet);

};
#endif
