#ifndef _xbCONFIGFILEPARSER_
#define _xbCONFIGFILEPARSER_
/*<<<***************************************************************************
The MIT License (MIT)

Copyright(C) 2013 - 2015 Marc Mirti Mancinelli, Christophe Lardau and Philippe Pamart (xdcube.org)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
////////////////////////////////////////////////////////////////////////////////
#Title: xbConfigFileParser
#Project: xdcBase
////////////////////////////////////////////////////////////////////////////////
#Author: Marc MIRTI MANCINELLI
#History:
<01/09/2013: creation.
12/02/2014: this notice inserted.
***************************************************************************>>>*/

#ifndef _xbCONFIGFILE_
#	include "xbConfigFile.h"
#endif

#ifndef _xbXML_
#	include "xbXml.h"
#endif

enum xbConfigXmlNodeType
{
	xbConfigXmlNode_Undef,
	xbConfigXmlNode_Root,
	xbConfigXmlNode_Key,
	xbConfigXmlNode_Value,
	xbConfigXmlNode_Comment
};

enum xbConfigXmlRootStatus
{
	xbConfigXmlRoot_Undef,
	xbConfigXmlRoot_Started,
	xbConfigXmlRoot_Stopped
};
class xbEXPORT __declspec(uuid("{275C103F-4183-44da-9682-996F50F45D6C}"))
	xbConfigXmlNode:public xbObject,
	public IxbXmlTarget
{
public:
	xbImplCreateObject(xbConfigXmlNode,xbConfigXmlNode);

	xbConfigXmlNode()
	{
		m_type = xbConfigXmlNode_Undef;
		m_valMode = xbCfgVal_Auto;
		m_cLf = 0;
		m_textColStart = 0;
		m_cp = 0;
		m_rootStatus = xbConfigXmlRoot_Undef;
		m_lastLine = 0;
	}
	virtual ~xbConfigXmlNode()
	{
		eProtectTrace(Destroy());
	}

	xbImplObject();

	virtual bool GetInterface(REFIID riid, void ** ppInterf)
	{
		xbImplInterface(IxbXmlTarget);
		xbImplInterface(xbConfigXmlNode);

		return xbObject::GetInterface(riid,ppInterf);
	}

	//IxbXmlTarget
	virtual void	AddSection(sIxbXmlSource *pSrce,const xbString &name,bool bSectTerminated,const xbXmlPos &sectPos);
	virtual void	AddSectionEnd(sIxbXmlSource *pSrce,const xbString &name,const xbXmlPos &sectPos);
	virtual void	AddText(sIxbXmlSource *pSrce,const xbString &text,const xbXmlPos &textPos);

	virtual int		CutSectionName(sIxbXmlSource *pSrce,const xbString &name,bool bEndSection,bool bSectTerminated);

	virtual bool	Warning(const xbString &file,int col,int line,const xbString &msg,LPCSTR pCtx);
	virtual bool	Error(const xbString &file,int col,int line,const xbString &msg,LPCSTR pCtx);

	virtual void	EndParse(sIxbXmlSource *pSrce,bool bOk);
	virtual xbString GetXmlLabel(sIxbXmlSource *pSrce);

	//Implementation
	bool EnumTagAndDetachVal(int &idx,xbString *pName, xbVariant *pValue,int *pOrder);
	bool EnumSection(int &idx,xbRefPtr<xbConfigXmlNode> *pprKey) const;
	xbConfigXmlNodeType GetType() const {return m_type;}
	xbCfgValMode		GetValMode() const {return m_valMode;}
	xbString GetName() const 
	{
		if (m_type == xbConfigXmlNode_Root)
			return "xdcube";
		return m_name;
	}
	int	GetLfLength() const {return m_cLf;}
	void GetValueAndDetach(xbVariant *pVar);
	void GetComment(xbStringW *pComment);
	void Clear(xbArray< xbRefPtr<IxbObject> > *pArrNodeRsrv);
	void InitNode(xbConfigXmlNodeType nodeType,ulong cp);
protected:
	void startSection(sIxbXmlSource *pSrce,xbConfigXmlNode *pParent,const xbString &name,bool bSectTerminated,int &lastLine,const xbXmlPos &sectPos);
	void endSection(sIxbXmlSource *pSrce,int &lastLine,const xbXmlPos &sectPos);

	xbConfigXmlNodeType m_type;
	xbCfgValMode		m_valMode;
	xbString			m_name,m_fullName;
	int					m_cLf,m_textColStart, m_lastLine;
	ulong				m_cp;
	xbStringW			m_text;
	xbConfigXmlRootStatus	m_rootStatus;
	xbArray<xbRefPtr<xbConfigXmlNode>> m_arrNode;

	struct Tag
	{
		xbString m_name;
		xbVariant m_value;
	};

	xbArray<Tag>		m_arrTag;
	xbStringW textTrunc(sIxbXmlSource *pSrce,const xbStringW &str);
};

class xbEXPORT __declspec(uuid("{B8004DAB-E873-4913-B730-DE29F3A134C7}"))
	xbConfigFileParser:public xbXmlParser
{
public:
	xbConfigFileParser(ulong cp,xbCfgKeyChangesInfo *pChgInfo,xbArray< xbRefPtr<IxbObject> > *pArrNodeRsrv);
	~xbConfigFileParser();

	virtual bool GetInterface(REFIID riid, void ** ppInterf)
	{
		xbImplInterface(xbConfigFileParser);
		return xbXmlParser::GetInterface(riid,ppInterf);
	}

	bool ParseStream(const xbString &fname,IxbInputStream *pStm);

	void cfgFileLoad(xbConfigFile *pKey);

protected:
	virtual void warning(const xbString &msg,int col = -1,int line = -1,LPCSTR pCtx = NULL);
	virtual void error(const xbString &msg,int col = -1,int line = -1,LPCSTR pCtx = NULL);

	IxbXmlTarget *createRootNode();
	xbRefPtr<xbConfigXmlNode> createNode();
	xbArray< xbRefPtr<IxbObject> >	*m_pArrNodeRsrv;
	xbCfgKeyChangesInfo				*m_pChgInfo;
	ulong							m_cp;
	bool							m_bXmlOk;

	xbRefPtr<xbConfigXmlNode>		m_prRoot;

	friend xbConfigXmlNode;
};

#endif
