/* -*- mia-c++ -*-
 *
 * This file is part of viewitgui - a library and program for the
 * visualization of 3D data sets. 
 *
 * Copyright (c) Leipzig, Madrid 1999-2013 Mirco Hellmann, Gert Wollny
 *
 * viewitgui is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * viewitgui 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 General Public License
 * along with viewitgui; if not, see <http://www.gnu.org/licenses/>.
 */


#ifdef HAVE_CONFIG_H
#include <config.h>
#endif


#include "userini.hh"
#include <libxml++/libxml++.h>


#ifdef LIBXML_OLD_VERSION
#define add_child_text add_content 
#define get_child_text get_child_content 
#endif

XMLini::XMLini() 
	: parser(NULL)
{
	parser = new xmlpp::DomParser;
	xmlpp::Element* nodeRoot = parser->get_document()->create_root_node("root"); 
}

XMLini::~XMLini()
{
	if (parser) delete parser;
}


bool XMLini::write_to_file(std::string &fn) 
{
	try {
		parser->get_document()->write_to_file(fn);	
	} catch (const std::exception& ex) {
		return true;
	}
	return false;
}
	

bool XMLini::read_from_file(std::string &fn)
{
	try {
		if (parser) delete parser;
		parser = new xmlpp::DomParser(fn);
		
	} catch (const std::exception& ex) {
		
		parser = new xmlpp::DomParser;
		xmlpp::Element* nodeRoot = parser->get_document()->create_root_node("root"); 		
		return true;
	}
	
	return false;
}
	
void XMLini::set_value(std::string const &section, std::string const &key, std::string const &value)
{
	xmlpp::Element* nodeRoot = parser->get_document()->get_root_node(); 
	xmlpp::Node::NodeList list = nodeRoot->get_children();
	
	xmlpp::Node::NodeList::iterator ibeg = list.begin();
	xmlpp::Node::NodeList::iterator iend = list.end();
	
	// search the given section
	while ( (ibeg != iend) && ((*ibeg)->get_name() != section) ) ibeg++;
	
	// if the desired section was not found -> create it
	if (ibeg == iend) {
		xmlpp::Element* nodeChild = nodeRoot->add_child(section);	
		nodeChild = nodeChild->add_child(key);
		nodeChild->add_child_text(value);
	} else {
		xmlpp::Element *nodeSection = dynamic_cast<xmlpp::Element*>(*ibeg);
		list = nodeSection->get_children();

		ibeg = list.begin();
		iend = list.end();
		
		while ( (ibeg != iend) && ((*ibeg)->get_name() != key) ) ibeg++;
		
		// if the desired key was not found -> create it
		if (ibeg == iend) {
			xmlpp::Element* nodeChild = nodeSection->add_child(key);	
			nodeChild->add_child_text(value);
		} else {
			xmlpp::Element *el = dynamic_cast<xmlpp::Element *>(*ibeg);
			if (el->get_child_text())
				el->remove_child(el->get_child_text());
			el->add_child_text(value);
		}
		
	}
		

}

bool XMLini::get_value(std::string &section, std::string &key, std::string &value) const
{
	xmlpp::Element* nodeRoot = parser->get_document()->get_root_node(); 
	xmlpp::Node::NodeList list = nodeRoot->get_children();
		
	xmlpp::Node::NodeList::iterator ibeg = list.begin();
	xmlpp::Node::NodeList::iterator iend = list.end();

	// find section
	while ( (ibeg != iend) && ((*ibeg)->get_name() != section) ) ibeg++;
	
	if (ibeg == iend) return false;
	
	// find key
	list = (*ibeg)->get_children();
	ibeg = list.begin();
	iend = list.end();
	while ( (ibeg != iend) && ((*ibeg)->get_name() != key) ) ibeg++;

	if (ibeg == iend) return false;

	if (dynamic_cast<xmlpp::Element*>(*ibeg)->get_child_text()) 
		value = dynamic_cast<xmlpp::Element*>(*ibeg)->get_child_text()->get_content();
	else 
		return false;
	
	return true;
}

bool XMLini::remove_section(const std::string &section)
{
	xmlpp::Element* nodeRoot = parser->get_document()->get_root_node(); 
	xmlpp::Node::NodeList list = nodeRoot->get_children();
	
	xmlpp::Node::NodeList::iterator ibeg = list.begin();
	xmlpp::Node::NodeList::iterator iend = list.end();

	// find section
	while ( (ibeg != iend) && ((*ibeg)->get_name() != section) ) ibeg++;
	
	if (ibeg == iend) return false;

	nodeRoot->remove_child(*ibeg);
	
	return true;
}
