/***************************************************************************
 *   Copyright (C) 2005 by Daniel Stöckel                                  *
 *   the_docter@gmx.net                                                    *
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   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 General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "configuration.h"

#include <qfile.h>
#include <stdlib.h>

#include "menulistviewitem.h"

Config::Config()
	:mTintColor(Qt::black),mOpacity(0.2f),mScheme("none"),mMenuButtonSize(32),mNavButtonSize(32),mMenuRadius(132),doc(NULL)
{
}

Config::~Config()
{
	if(doc){
		delete doc;
	}
}

bool Config::readConfigFile( )
{
	QFile file(mConfigPath);
	if(!file.open(IO_ReadOnly)){
		return false;
	}
	if(doc){
		delete doc;
	}
	doc = new QDomDocument();
	doc->setContent( &file );
	file.close();

	if(doc){
		QDomNode topLevelNode = doc->documentElement().firstChild();
		while(!topLevelNode.isNull()){
			if(topLevelNode.isElement()){
				QDomElement elem = topLevelNode.toElement();
				if(elem.tagName()=="access"){
					setShortcut(elem.text());
				} else if(elem.tagName()=="tintcolor"){
					mTintColor.setNamedColor(elem.text());
				} else if(elem.tagName()=="opacity"){
					mOpacity=atof(elem.text());
				}else if(elem.tagName()=="menubuttonsize"){
					mMenuButtonSize=atoi(elem.text());
				}else if(elem.tagName()=="navbuttonsize"){
					mNavButtonSize=atoi(elem.text());
				}else if(elem.tagName()=="menuradius"){
					mMenuRadius=atoi(elem.text());
				}else if(elem.tagName()=="scheme"){
					mScheme=elem.text();
			    }
			}
			topLevelNode = topLevelNode.nextSibling();
		}
	}
	return true;
}

bool Config::writeConfigFile( )
{
	if(!doc){
		return false;
	}
	QFile file(mConfigPath);
	if(!file.open(IO_WriteOnly)){
		return false;
	}
	QTextStream str(&file);
	str << *doc;
	file.close();
	return true;
}

void Config::fromConfigDlg( const QListView* listView )
{
	if(doc){
		delete doc;
	}
	doc = new QDomDocument();
	QDomElement root=doc->createElement("root");
	doc->appendChild(root);

	newNode("access",root,Shortcut(),"method","shortcut");
	newNode("menubuttonsize",root,mMenuButtonSize);
	newNode("navbuttonsize",root,mNavButtonSize);
	newNode("tintcolor",root,tintColor().name());
	newNode("opacity",root,mOpacity);
	newNode("menuradius",root,static_cast<int>(mMenuRadius));
	newNode("scheme",root,mScheme);

	QDomElement node=doc->createElement("menu");
	QListViewItem* temp = listView->firstChild();
	while(temp){
		menuItemToXML(node,static_cast<MenuListViewItem*>(temp));
		temp=temp->nextSibling();
	}
	root.appendChild(node);
}

//ARGHHH!! I need this function because QListView::lastItem returns not only top level items but also children of top level items
//It took me hours of my precious lifetime to figure that out!! _Terribly_ annoying -.-
QListViewItem* lastChild(QListView* view)
{
	QListViewItem* temp=view->firstChild();
	QListViewItem* item=NULL;
	while(temp!=NULL){
		item=temp;
		temp=temp->nextSibling();
	}
	return item;
}

void Config::toListView(QListView* listView )
{
	listView->clear();
	if(doc){
		QDomNode topLevelNode = doc->documentElement().firstChild();
		while(!topLevelNode.isNull()){
			if(topLevelNode.isElement()){
				if((topLevelNode.toElement().tagName()=="menu")&&topLevelNode.hasChildNodes())
				{
					QDomNode menuNode=topLevelNode.firstChild();
					
					while(!menuNode.isNull()){
						if(menuNode.isElement()){
							QDomElement elemNode=menuNode.toElement();
							menuItemFromXML(listView,lastChild(listView),menuNode.toElement());
						}
						menuNode = menuNode.nextSibling();
					}
				}
			}
			topLevelNode = topLevelNode.nextSibling();
		}
	}
}

void Config::toKommandoMenu(Kommando* buttonParent)
{
	if(doc){
		QDomNode node = doc->documentElement().firstChild();
		
		while(!node.isNull()){
			if(node.isElement()&&(node.toElement().tagName()=="menu")){
				break;
			}
			node=node.nextSibling();
		}
		Menu* mainMenu= menuFromXML(node.toElement(),buttonParent);
		mainMenu->arrangeButtons();
		buttonParent->resize();
		buttonParent->setMainMenu(mainMenu);
		buttonParent->setActMenu(mainMenu);
		buttonParent->setNavButtonSize(mNavButtonSize);
	}
}

void Config::setDefaultValues()
{
	setTintColor(Qt::black);
	setOpacity(0.2f);
	setShortcut("Alt+Ctrl+H");
	setNavButtonSize(32);
	setMenuButtonSize(32);
	setMenuRadius(132);
	setScheme("Normal");
	
	if(doc){
		delete doc;
	}
	doc = new QDomDocument();
	QDomElement root=doc->createElement("root");
	doc->appendChild(root);

	newNode("access",root,Shortcut(),"method","shortcut");
	newNode("menubuttonsize",root,32);
	newNode("navbuttonsize",root,32);
	newNode("tintcolor",root,"#000000");
	newNode("opacity",root,0.2f);
	newNode("menuradius",root,132);
	newNode("scheme",root,"Normal");

	QDomElement node= newMenu(root,"");
	newButton(node,"konsole","konsole --workdir $HOME");
	newButton(node,"kwrite","kwrite");
	newButton(node,"konqueror","konqueror");
	newButton(node,"kcalc","kcalc");
	newButton(node,"gimp","gimp");
	newButton(node,"kfm_home","kfmclient openProfile filemanagement");
	node=newMenu(node,"kmix");
	newButton(node,"kmix","kmix");
	newButton(node,"k3b","k3b");
	newButton(node,"amarok","amarok");
	newButton(node,"kaffeine","kaffeine");
}

Menu * Config::menuFromXML( const QDomElement & ownNode, Kommando * buttonParent, Menu* parent)
{
	QString iconpath;
	QDomNode node=ownNode.firstChild();
	
	Menu* newMenu = new Menu(parent);
	
	while(!node.isNull()){
		if(node.isElement()){
			ExtendedButton* button;
			if(node.nodeName() == "button"){
				button = comButtonFromXML(node.toElement(),buttonParent);
				newMenu->insert(button);
			} else if(node.nodeName()=="menu"){
				Menu* subMenu = menuFromXML(node.toElement(),buttonParent,newMenu);				//establish all necessary connections, e.g. menu structure
				button = new SubmenuButton(buttonParent,subMenu,mMenuButtonSize);
				newMenu->insert(button);
				newMenu->addChild(subMenu);
				button->setIcon(subMenu->IconPath());
			} else if(node.nodeName()=="icon"){
				newMenu->setIconPath(node.firstChild().nodeValue());
			}
		}
		node=node.nextSibling();
	}
	
	newMenu->hideButtons();
	
	return newMenu;
}

CommandoButton* Config::comButtonFromXML(const QDomElement& ownNode, Kommando* parent)
{
	CommandoButton* button = new CommandoButton(parent,mMenuButtonSize);

	QDomNode bnode=ownNode.firstChild();
	while (!bnode.isNull()){
		if(bnode.nodeName() == "command"){
			button->setCommand(bnode.firstChild().nodeValue());
		} else if (bnode.nodeName() == "icon"){
			button->setIcon(bnode.firstChild().nodeValue());
		}
		bnode=bnode.nextSibling();
	}
	return button;
}

QDomElement Config::newNode( const QString& nodename, QDomNode& parent, int value )
{
	QDomElement node=doc->createElement(nodename);
	node.appendChild(doc->createTextNode(QString::number(value)));
	parent.appendChild(node);
	
	return node;
}

QDomElement Config::newNode( const QString& nodename, QDomNode& parent, float value )
{
	QDomElement node=doc->createElement(nodename);
	node.appendChild(doc->createTextNode(QString::number(value)));
	parent.appendChild(node);
	
	return node;
}

QDomElement Config::newNode( const QString& nodename, QDomNode& parent, const QString& value )
{
	QDomElement node=doc->createElement(nodename);
	node.appendChild(doc->createTextNode(value));
	parent.appendChild(node);

	return node;
}

QDomElement Config::newNode( const QString& nodename, QDomNode& parent, const QString& value, const QString& attrname, const QString& attrvalue )
{
	QDomElement node=doc->createElement(nodename);
	node.setAttribute(attrname,attrvalue);
	node.appendChild(doc->createTextNode(value));
	parent.appendChild(node);
	
	return node;
}

QDomElement Config::newButton(QDomNode& parent, const QString& icon, const QString& command )
{
	QDomElement root = doc->createElement("button");
	if(command!=""){
		QDomElement node = doc->createElement("command");
		node.appendChild(doc->createTextNode(command));
		root.appendChild(node);
	}
	if(icon!=""){
		QDomElement node=doc->createElement("icon");
		node.appendChild(doc->createTextNode(icon));
		root.appendChild(node);
	}
	parent.appendChild(root);
	return root;
}

QDomElement Config::newMenu( QDomNode & parent, const QString& icon )
{
	QDomElement root = doc->createElement("menu");
	if(icon!=""){
		QDomElement node=doc->createElement("icon");
		node.appendChild(doc->createTextNode(icon));
		root.appendChild(node);
	}
	parent.appendChild(root);
	return root;
}

void Config::menuItemToXML( QDomNode & parent, MenuListViewItem* item)
{
	if(item->type()==MenuListViewItem::Menu){
		QDomElement node = newMenu(parent,item->iconPath());
		QListViewItem* temp = item->firstChild();
		while(temp){
			menuItemToXML(node,static_cast<MenuListViewItem*>(temp));
			temp=temp->nextSibling();
		}
	} else if(item->type()==MenuListViewItem::Button){
		newButton(parent,item->iconPath(),item->text(1));
	}
}

void Config::menuItemFromXML(QListView* parent, QListViewItem* after, const QDomElement& ownNode)
{
	MenuListViewItem* item;
	if (ownNode.tagName()=="menu"){
		item = new MenuListViewItem(parent,after,"Menu",MenuListViewItem::Menu);
		item->setOpen(true);
	} else if (ownNode.tagName()=="button"){
		item = new MenuListViewItem(parent,after,"Button",MenuListViewItem::Button);
	} else return;
	itemHelper(ownNode,item);   //Parse properties and children of this item
}

void Config::menuItemFromXML(QListViewItem* parent, QListViewItem* after, const QDomElement& ownNode)
{
	MenuListViewItem* item;
	if (ownNode.tagName()=="menu"){
		item = new MenuListViewItem(parent,after,"Menu",MenuListViewItem::Menu);
		item->setOpen(true);
	} else if (ownNode.tagName()=="button"){
		item = new MenuListViewItem(parent,after,"Button",MenuListViewItem::Button);
	} else return;
	
	itemHelper(ownNode,item);  //Parse properties and children of this item
}

void Config::itemHelper(const QDomElement& ownNode, MenuListViewItem* item)
{
	QDomNode temp = ownNode.firstChild();
	
	while(!temp.isNull()){
		if(temp.isElement()){
			QDomElement temp2=temp.toElement();
			if(temp2.tagName()=="icon"){
				item->setIconPath(temp2.firstChild().nodeValue());
			} else if((temp2.tagName()=="command")&&(item->type()==MenuListViewItem::Button)){
				item->setText(1,temp2.firstChild().nodeValue());
			//is item a menu? otherwise parsing buttons and submenus would not make sense
			} else if(((temp2.tagName()=="menu")||(temp2.tagName()=="button"))&&(item->type()==MenuListViewItem::Menu)){
				menuItemFromXML(item,item->lastChild(),temp2);  //Note to self: es liegt nicht an der ordnung in der die kinder hinzugefügt werden!!!
			}
		}
		temp=temp.nextSibling();
	}
}
