#include "ManagementObjects/TNDSMgmtTree/TNDSExtractor.h"
#include "Common.h"
#include "common/Utils.h"
#include <syncml/core/ObjectDel.h>
#include <base/util/XMLProcessor.h>

//-------------------------------------------------------------------------------------------

const char* const c_cdata_prefix = "<![CDATA[";
const char* const c_cdata_suffix = "]]>";

//-------------------------------------------------------------------------------------------

namespace NS_DM_Client
{
	TNDSExtractor::TNDSExtractor(const String& xml): m_buffer(xml), m_curPos(0)
	{
	}
	//-------------------------------------------------------------------------------------------

	void TNDSExtractor::GetValue(const String& name, String& value)
	{
		size_t pos = 0;
		unsigned int curPos = 0;
		unsigned int start = 0;
		unsigned int end = 0;
		const char* node = Funambol::XMLProcessor::getElementContent(m_buffer.c_str(), S_node.c_str(), 0, &start, &end);

		while (node)
		{
			curPos += end;
			node = Funambol::XMLProcessor::copyContent(&m_buffer.c_str()[pos], start, end);
			Funambol::XMLProcessor::getElementContent(node, S_nodeName.c_str(), 0, &start, &end);
			const char* nodeName = Funambol::XMLProcessor::copyContent(node, start, end);
			if (name == nodeName)
			{
				Funambol::XMLProcessor::getElementContent(node, S_value.c_str(), 0, &start, &end);
				char* tmpValue = Funambol::XMLProcessor::copyContent(node, start, end);
				value = tmpValue;
				delete [] tmpValue;
				delete [] nodeName;
				delete [] node;
				break;
			}
			pos = curPos;
			delete [] nodeName;
			delete [] node;
			node = Funambol::XMLProcessor::getElementContent(&m_buffer.c_str()[curPos], S_node.c_str(), 0, &start, &end);
		}
	}
	//-------------------------------------------------------------------------------------------
//// 2011.05.02
	void TNDSExtractor::GetValue(const String& name, bool& value)
	{
		size_t pos = 0;
		unsigned int curPos = 0;
		unsigned int start = 0;
		unsigned int end = 0;
		const char* node = Funambol::XMLProcessor::getElementContent(m_buffer.c_str(), S_node.c_str(), 0, &start, &end);

		while (node)
		{
			curPos += end;
			node = Funambol::XMLProcessor::copyContent(&m_buffer.c_str()[pos], start, end);
			Funambol::XMLProcessor::getElementContent(node, S_nodeName.c_str(), 0, &start, &end);
			const char* nodeName = Funambol::XMLProcessor::copyContent(node, start, end);
			if (name == nodeName)
			{
				Funambol::XMLProcessor::getElementContent(node, S_value.c_str(), 0, &start, &end);
				char* tmpValue = Funambol::XMLProcessor::copyContent(node, start, end);
                (bool&)value = false;
				if(strcmp(tmpValue, "true") == 0) (bool&)value = true;
				delete [] tmpValue;
				delete [] nodeName;
				delete [] node;
				break;
			}
			pos = curPos;
			delete [] nodeName;
			delete [] node;
			node = Funambol::XMLProcessor::getElementContent(&m_buffer.c_str()[curPos], S_node.c_str(), 0, &start, &end);
		}
	}
	//-------------------------------------------------------------------------------------------

	void TNDSExtractor::GetValue(const String& path, const String& name, String& value)
	{
		size_t pos = 0;
		unsigned int curPos = 0;
		unsigned int start = 0;
		unsigned int end = 0;
		const char* node = Funambol::XMLProcessor::getElementContent(m_buffer.c_str(), S_node.c_str(), 0, &start, &end);

		while (node)
		{
			curPos += end;
			node = Funambol::XMLProcessor::copyContent(&m_buffer.c_str()[pos], start, end);
			Funambol::XMLProcessor::getElementContent(node, S_nodeName.c_str(), 0, &start, &end);
			const char* nodeNameXml = Funambol::XMLProcessor::copyContent(node, start, end);
			if (name == nodeNameXml)
			{
				Funambol::XMLProcessor::getElementContent(node, S_path.c_str(), 0, &start, &end);
				const char* pathXml = Funambol::XMLProcessor::copyContent(node, start, end);
				if (path == pathXml)
				{
					if (Funambol::XMLProcessor::getElementContent(node, S_value.c_str(), 0, &start, &end))
					{
						char* tmpValue = Funambol::XMLProcessor::copyContent(node, start, end);
						value = tmpValue;

						filterNodeValue(value);

						delete [] tmpValue;
					}
					else
					{
						value = "";
					}

					delete [] nodeNameXml;
					delete [] node;
					delete [] pathXml;
					break;
				}
				delete [] pathXml;
			}
			pos = curPos;
			delete [] nodeNameXml;
			delete [] node;
			node = Funambol::XMLProcessor::getElementContent(&m_buffer.c_str()[curPos], S_node.c_str(), 0, &start, &end);
		}
	}
	//-------------------------------------------------------------------------------------------

	void TNDSExtractor::GetChildren(const String& parent, Children& children)
	{
		size_t pos = 0;
		unsigned int curPos = 0;
		unsigned int start = 0;
		unsigned int end = 0;
		const char* node = Funambol::XMLProcessor::getElementContent(m_buffer.c_str(), S_node.c_str(), 0, &start, &end);

		while (node)
		{
			curPos += end;
			node = Funambol::XMLProcessor::copyContent(&m_buffer.c_str()[pos], start, end);
			Funambol::XMLProcessor::getElementContent(node, S_nodeName.c_str(), 0, &start, &end);
			const char* nodeName = Funambol::XMLProcessor::copyContent(node, start, end);
			Funambol::XMLProcessor::getElementContent(node, S_path.c_str(), 0, &start, &end);
			const char* path = Funambol::XMLProcessor::copyContent(node, start, end);
			if (path == parent)
			{
				children.push_back(nodeName);
			}
			pos = curPos;
			delete [] path;
			delete [] nodeName;
			delete [] node;
			node = Funambol::XMLProcessor::getElementContent(&m_buffer.c_str()[curPos], S_node.c_str(), 0, &start, &end);
		}
	}
	//-------------------------------------------------------------------------------------------

	int TNDSExtractor::GetCount(const String& tagValue, const String& tagName/* = "Path"*/)
	{
		size_t pos = 0;
		unsigned int curPos = 0;
		unsigned int start = 0;
		unsigned int end = 0;
		const char* node = Funambol::XMLProcessor::getElementContent(m_buffer.c_str(), S_node.c_str(), 0, &start, &end);

		int count = 0;
		while (node)
		{
			curPos += end;
			node = Funambol::XMLProcessor::copyContent(&m_buffer.c_str()[pos], start, end);
			Funambol::XMLProcessor::getElementContent(node, tagName.c_str(), 0, &start, &end);
			const char* value = Funambol::XMLProcessor::copyContent(node, start, end);
			if (tagValue == value)
			{
				++count;
			}
			pos = curPos;
			delete [] value;
			delete [] node;
			node = Funambol::XMLProcessor::getElementContent(&m_buffer.c_str()[curPos], S_node.c_str(), 0, &start, &end);
		}
		return count;
	}
	//-------------------------------------------------------------------------------------------

	void TNDSExtractor::GetValue(const String& name, size_t& value)
	{
		String strValue;
		GetValue(name, strValue);
		value = atoi(strValue.c_str());
	}
	//-------------------------------------------------------------------------------------------

	void TNDSExtractor::GetValue(const String& path, const String& name, size_t& value)
	{
		String strValue;
		GetValue(path, name, strValue);
		value = atoi(strValue.c_str());
	}
	//-------------------------------------------------------------------------------------------

	void TNDSExtractor::GetValue(const String& path, const String& name, bool& value)
	{
		String strValue;
		GetValue(path, name, strValue);
		value = IsBooleanTrue(strValue);
	}
	//-------------------------------------------------------------------------------------------

	void TNDSExtractor::GetValue(const String& path, const String& name, unsigned char& value)
	{
		String strValue;
		GetValue(path, name, strValue);
		value = atoi(strValue.c_str());
	}
	//-------------------------------------------------------------------------------------------

	void TNDSExtractor::GetValue(const String& name, unsigned char& value)
	{
		String strValue;
		GetValue(name, strValue);
		value = atoi(strValue.c_str());
	}
	//-------------------------------------------------------------------------------------------

	void TNDSExtractor::GetValue(const String& name, int& value)
	{
		String strValue;
		GetValue(name, strValue);
		value = atoi(strValue.c_str());
	}
	//-------------------------------------------------------------------------------------------

	void TNDSExtractor::GetValue(const String& path, const String& name, int& value)
	{
		String strValue;
		GetValue(path, name, strValue);
		value = atoi(strValue.c_str());
	}
	//-------------------------------------------------------------------------------------------

	bool TNDSExtractor::Exist(const String& path, const String& name)
	{
		return false;
	}
	//-------------------------------------------------------------------------------------------

	bool TNDSExtractor::SerializeToTree(IMOTreeManager& treeManager)
	{
		size_t pos = 0;
		unsigned int curPos = 0;
		unsigned int start = 0;
		unsigned int end = 0;
		const char* node = Funambol::XMLProcessor::getElementContent(m_buffer.c_str(), S_node.c_str(), 0, &start, &end);

		bool brc = true;
		while (node)
		{
			curPos += end;
			node = Funambol::XMLProcessor::copyContent(&m_buffer.c_str()[pos], start, end);
			brc &= parseNode(node, treeManager);
			pos = curPos;
			delete [] node;
			node = Funambol::XMLProcessor::getElementContent(&m_buffer.c_str()[curPos], S_node.c_str(), 0, &start, &end);
		}
		delete [] node;
		return brc;
	}
	//-------------------------------------------------------------------------------------------

	bool TNDSExtractor::parseNode(const char* node, IMOTreeManager& treeManager)
	{
		String nodeName;
		bool res = getNodeValue(node, S_nodeName, nodeName);
		if (!res)
			return false;
		String path;
		res &= getNodeValue(node, S_path, path);

		String value;
		res &= getNodeValue(node, S_value, value);

		String format;
		res &= getNodeValue(node, S_format, format);

		String acl;
		res &= getNodeValue(node, S_acl, acl);

		String type;
		res &= getNodeValue(node, S_type, type);

		res &= SerializeItemToTree(path + S_slash + nodeName, value, treeManager, format, acl, type);

		return res;
	}
	//-------------------------------------------------------------------------------------------

	bool TNDSExtractor::getNodeValue(const char* node, const String& name, String& value)
	{
		unsigned int start = 0;
		unsigned int end = 0;

		Funambol::XMLProcessor::getElementContent(node, name.c_str(), 0, &start, &end);
		char* valueXml = Funambol::XMLProcessor::copyContent(node, start, end);
		if (!valueXml)
			return false;
		value = valueXml;
		delete [] valueXml;

		return true;
	}

	//-------------------------------------------------------------------------------------------

	void TNDSExtractor::filterNodeValue(String& value)
	{
		if (value.find(c_cdata_prefix) == 0)
		{
			size_t suffix_pos = value.find(c_cdata_suffix);
			if(suffix_pos != String::npos)
			{
				size_t prefix_size = strlen(c_cdata_prefix);
				value = value.substr(prefix_size, suffix_pos - prefix_size);
			}
		}
	}

	//-------------------------------------------------------------------------------------------

}
