/*
 * Copyright (C) 2009 - 2010 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

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

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)
				{
					Funambol::XMLProcessor::getElementContent(node, S_value.c_str(), 0, &start, &end);
					char* tmpValue = Funambol::XMLProcessor::copyContent(node, start, end);
					value = tmpValue;
					delete [] tmpValue;
					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);

		while (node)
		{
			curPos += end;
			node = Funambol::XMLProcessor::copyContent(&m_buffer.c_str()[pos], start, end);
			bool res = 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 true;
	}
	//-------------------------------------------------------------------------------------------

	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;
	}

		
}
