//
// C++ Implementation: xmldata
//
// Description: 
//
//
// Author: Benjamin Mesing,,, <bensmail@gmx.net>, (C) 2004
//
// Copyright: See COPYING file that comes with this distribution
//
//

#include <iostream>
#include <fstream>

#include <qmessagebox.h>

#include "xmldata.h"

#include "helpers.h"

using namespace std;

namespace NXml
{

QDomElement getFirstChild(QDomNode node)
{
	while (!node.isNull())
	{
		if (!node.toElement().isNull())	// if the node is an element
			return node.toElement();
		node = node.nextSibling();
	}
	return node.toElement();	// returns the null element
}


QDomElement getFirstElement(QDomNode node)
{
	while (!node.isNull())
	{
		if (node.isElement())	// if the node is an element
			return node.toElement();
		node = node.nextSibling();
	}
	return node.toElement();	// returns the null element
}

QDomElement getNextElement(QDomNode node)
{
	return getFirstElement(node.nextSibling());
}


XmlData::XmlData()
{
}

XmlData::XmlData(const QString& name)
{
	_domDocument = QDomDocument(name);
	_domDocument.appendChild(_domDocument.createElement(name));
}

XmlData::XmlData(QDomDocument document)
{
	_domDocument = document;
}


XmlData::~XmlData()
{
}

bool XmlData::loadFile(const QString& filename)
{
	QFile file(filename);
    if (!file.open(QIODevice::ReadOnly)) {
        return false;
    }
	_domDocument = QDomDocument();
    QString parseErrorMessage = QString();
    if (!_domDocument.setContent(&file, false, &parseErrorMessage))	// parse das XML Document
	{
        qWarning() << "Unable to parse config file $HOME/.packagesearch:\n" << parseErrorMessage;
        file.close();
		return false;
	}
    file.close();
	return true;
}

QDomElement XmlData::startDocument(const QString& name)
{
	_domDocument = QDomDocument(name);
	QDomElement root = _domDocument.createElement(name);
	_domDocument.appendChild(root);
	return root;

}

void XmlData::xmlifyString(QString& string)
{
	string.replace('&', "&amp");
	string.replace('<', "&lt");
	string.replace('>', "&gt");
	string.replace('\'', "&apos");
	string.replace('\"', "&quot");
}

void XmlData::xmlifyStringList(QStringList& stringList)
{
	QStringList::iterator end=stringList.end();
	for (QStringList::iterator i=stringList.begin(); i!=end; ++i)
		xmlifyString( *i );
}

QDomElement XmlData::addElement(QDomElement parent, const QString& tagName)
{
	QDomElement element = _domDocument.createElement(tagName);
	parent.appendChild(element);
	return element;
}

QDomText XmlData::addText(QDomElement element, QString text)
{
	xmlifyString(text);
	QDomText textNode = _domDocument.createTextNode(text);
	element.appendChild(textNode);
	return textNode;
}

QDomText XmlData::addText(QDomElement element, const string& text)
{
	QString newText = toQString(text);
	xmlifyString(newText);
	QDomText textNode = _domDocument.createTextNode(newText);
	element.appendChild(textNode);
	return textNode;
}

void XmlData::addText(QDomElement element, QString tagName, QStringList text)
{
	for (QStringList::iterator it = text.begin(); it != text.end(); ++it)
	{
		QDomElement subElement = addElement(element, tagName);
		addText(subElement, *it);
	}
}


QDomAttr XmlData::addAttribute(QDomElement node, const QString& value, const QString& name )
{
	QDomAttr attribute = _domDocument.createAttribute(name);
	QString copyValue(value);
	xmlifyString(copyValue);
	attribute.setValue(copyValue);
	node.setAttributeNode(attribute);
	return attribute;
}

QDomAttr XmlData::addAttribute(QDomElement node, const string& value, const QString& name)
{
	return addAttribute(node, toQString(value), name);
}

QDomAttr XmlData::addAttribute(QDomElement node, uint value, const QString& name)
{
	QString tmp;
	tmp.setNum(value);
	return addAttribute(node, tmp, name);
}

QDomAttr XmlData::addAttribute(QDomElement node, int value, const QString& name)
{
	QString tmp;
	tmp.setNum(value);
	return addAttribute(node, tmp, name);
}

QDomAttr XmlData::addAttribute(QDomElement node, double value, const QString& name)
{
	QString tmp;
	tmp.setNum(value);
	return addAttribute(node, tmp, name);
}


QDomAttr XmlData::addAttribute(QDomElement node, bool value, const QString& name)
{
	return addAttribute(node, (value==false)? 0 : 1, name);
}

QDomElement XmlData::importNode(QDomElement src, QDomElement dst, bool deep)
{
	QDomElement imported = _domDocument.importNode(src, deep).toElement();
	dst.appendChild(imported);
	return imported;
}

bool XmlData::skipComments(QDomNode& node)
{
	if (node.nodeType() != QDomNode::CommentNode ) return false;
	node = node.nextSibling();
	while (node.nodeType() == QDomNode::CommentNode)	// skip the comments
		node = node.nextSibling();
	return true;
}

bool XmlData::writeFile(const QString& filename) const
{
    ofstream out(filename.toLatin1(), ios::out);
	if (!out.good()) out.close();
	if (!out.is_open())
	{
		QString errorMsg(filename);
		errorMsg="Couldn't open file "+errorMsg;
		return false;
	}
	out << toString(_domDocument.toString());
	out.close();
	return true;
}



/////////////////////////////////////////////////////
// getAttribute functions
/////////////////////////////////////////////////////

bool getAttribute(QDomElement element, QString& loadInto, const QString& name, QString def)
{
	const QDomAttr attribute = element.attributeNode(name);
	if (attribute.isNull())
	{
		loadInto=def;
		#ifdef DEBUG
			cout << "Attribute "<<name << " not found. Using default value "<<def;
		#endif
		return false;
	}
	else
	{
		loadInto = attribute.value();
		return true;
	}
}

bool getAttribute(QDomElement element, string& loadInto, const QString& name, string def)
{
	QString tmp;
	bool success = getAttribute(element, tmp, name, toQString(def));
	loadInto = toString(tmp);
	return success;
}

bool getAttribute(QDomElement element, double& loadInto, const QString& name, double def)
{
	QString value;
	if (!getAttribute(element, value, name))
	{
		loadInto = def;
		return false;	// if the loading of the attribute as text failed
	}
	bool success;
	loadInto = value.toDouble(&success);
	if (!success)
		loadInto = def;
	return success;
}

bool getAttribute(QDomElement element, float& loadInto, const QString& name, float def)
{
	QString value;
	if (!getAttribute(element, value, name))
	{
		loadInto = def;
		return false;	// if the loading of the attribute as text failed
	}
	bool success;
	loadInto = value.toFloat(&success);
	if (!success)
		loadInto = def;
	return success;
}

bool getAttribute(QDomElement element, uint& loadInto, const QString& name, uint def)
{
	QString value;
	if (!getAttribute(element, value, name))
	{
		loadInto = def;
		return false;	// if the loading of the attribute as text failed
	}
	bool success;
	loadInto = value.toUInt(&success);
	if (!success)
		loadInto = def;
	return success;
}

bool getAttribute(QDomElement element, int& loadInto, const QString& name, int def)
{
	QString value;
	if (!getAttribute(element, value, name))
	{
		loadInto = def;
		return false;	// if the loading of the attribute as text failed
	}
	bool success;
	loadInto = value.toInt(&success);
	if (!success)
		loadInto = def;
	return success;
}

bool getAttribute(QDomElement element, bool& loadInto, const QString& name, bool def)
{
	QString value;
	if (!getAttribute(element, value, name))
	{
		loadInto = def;
		return false;	// if the loading of the attribute as text failed
	}
	bool success;
	int tmp = value.toInt(&success);
	loadInto = bool(tmp);	// 0 becomes false everything else true
	if (!success)
		loadInto = def;
	return success;
}

bool getAttribute(QDomElement element, uchar& loadInto, const QString& name, uchar def)
{
	QString value;
	if (!getAttribute(element, value, name))
	{
		loadInto = def;
		return false;	// if the loading of the attribute as text failed
	}
	bool success;
	ushort tmp = value.toUShort(&success);
	if (tmp > 255)
		success = false;
	loadInto = uchar(tmp);	// 0 becomes false everything else true
	if (!success)
		loadInto = def;
	return success;
}

QStringList getTextList(QDomElement element)
{	
	QStringList result;
	QDomElement child = getFirstElement(element.firstChild());
	while (!child.isNull())
	{
		QDomText text = child.firstChild().toText();
		// if the first child was a text node
		if (!text.isNull())
		{
			result.push_back(text.nodeValue());
		}
		child = getNextElement(child);
	}
	return result;
}

}	// NXml








