/***************************************************************************
 *   Copyright (C) 2004 by Juanjo                                          *
 *   juanjux@yahoo.es                                                      *
 *                                                                         *
 *   Copyright (C) 2004 by Mario Bensi                                     *
 *   nef@ipsquad.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.,                                       *
 *   51 Franklin Steet, Fifth Floor, Boston, MA  02111-1307, USA.          *
 ***************************************************************************/

#include "tdealternatives.h"
#include "altparser.h"
#include "propertieswindow.h"
#include "altcontroller.h"
#include "altitemelement.h"
#include "treeitemelement.h"
#include "addalternatives.h"
#include "mainwindow.h"

#include <tqtimer.h>

#include <tdemessagebox.h>
#include <tdeaboutdialog.h>
#include <ktextedit.h>
#include <kdebug.h>
#include <tdelocale.h>
#include <tqlayout.h>
#include <tqfile.h>
#include <tqtextstream.h>
#include <kgenericfactory.h>
#include <kstdguiitem.h>
#include <tdeversion.h>

#include "config.h"

typedef KGenericFactory<TDEAlternatives, TQWidget> TDEAlternativesFactory;
K_EXPORT_COMPONENT_FACTORY( kcm_tdealternatives, TDEAlternativesFactory("kcm_tdealternatives"))

extern "C"
{
	TDECModule *create_alternatives(TQWidget *parent, const char *name)
	{
		TDEGlobal::locale()->insertCatalogue("tdealternatives");
		return new TDEAlternatives(parent, name);
	};
}

TDEAlternatives::TDEAlternatives(TQWidget *parent, const char *name, const TQStringList&)
:TDECModule(/*TDEAlternativesFactory::instance(), */parent, name), myAboutData(0)
{
	setUseRootOnlyMsg(false);

	int user = getuid();
	
	if (user == 0)
	{
		m_bisRoot = true;
		setButtons(TDECModule::Help|TDECModule::Apply);
	}
	else 
	{
		m_bisRoot = false;
		setButtons(Help);
	}

#ifdef WITH_DISTRIBUTION_RPM
m_mgr = new AltFilesManager("/var/lib/rpm/alternatives");
#else
	#ifdef WITH_DISTRIBUTION_DPKG
	m_mgr = new AltFilesManager("/var/lib/dpkg/alternatives");
	#else
	KMessageBox::sorry(this,
		i18n("TDEAlternatives only works on systems which use the DPKG or RPM package manager."),
		i18n("Wrong System Type"));
	TQTimer::singleShot(0, this, TQ_SLOT(die()));
	#endif
#endif
	
	MainWindow *mainwindow = new MainWindow(this);
	TQBoxLayout *layout = new TQVBoxLayout(this, 0, KDialog::spacingHint());
	layout->addWidget( mainwindow );
	layout->activate();
	
	mainwindow->m_altList->setShowToolTips(1);
	
	connect(mainwindow->m_hideAlt, TQ_SIGNAL(clicked()), this,
			TQ_SLOT(slotHideAlternativesClicked()));
	
	connect(mainwindow->m_altList, TQ_SIGNAL(selectionChanged( TQListViewItem* )), this,
			TQ_SLOT(slotSelectAlternativesClicked(TQListViewItem *)));
	
	connect(mainwindow->m_optionsList, TQ_SIGNAL(clicked(TQListViewItem *)),
			this, TQ_SLOT(slotOptionClicked(TQListViewItem *)));
	connect(mainwindow->m_bAdd, TQ_SIGNAL(clicked()), this,
			TQ_SLOT(slotAddClicked()));
	connect(mainwindow->m_bDelete, TQ_SIGNAL(clicked()), this,
			TQ_SLOT(slotDeleteClicked()));
	connect(mainwindow->m_bProperties, TQ_SIGNAL(clicked()), this,
			TQ_SLOT(slotPropertiesClicked()));
	
	m_altList = mainwindow->m_altList;
	m_optionsList = mainwindow->m_optionsList;
	m_altTilte = mainwindow->m_altTilte;
	m_statusCombo = mainwindow->m_statusCombo;
	m_hideAlt = mainwindow->m_hideAlt;
	
	mainwindow->m_bDelete->setGuiItem(KStdGuiItem::del());
	mainwindow->m_bAdd->setGuiItem(KGuiItem(i18n("&Add"), "edit_add"));
	mainwindow->m_bProperties->setGuiItem(KGuiItem( i18n( "&Properties" ), "configure"));
	
	if(!m_bisRoot)
	{
		mainwindow->m_bDelete->setEnabled(false);
		mainwindow->m_bAdd->setEnabled(false);
		mainwindow->m_bProperties->setEnabled(false);
		m_statusCombo->setEnabled(false);
	}
	
	myAboutData = new TDEAboutData("kcm_tdealternatives", I18N_NOOP("Alternatives"),
	                                VERSION, I18N_NOOP("DPKG/RPM alternatives manager for TDE"),
	TDEAboutData::License_GPL, I18N_NOOP("(c) 2004 Juanjo Alvarez Martinez\n"
	                                     "(c) 2004 Mario Bensi"));

	myAboutData->addAuthor("Juanjo Alvarez Martinez", 0, "juanjo@juanjoalvarez.net",
		"http://juanjoalvarez.net");
	myAboutData->addAuthor("Mario Bensi", 0, "nef@ipsquad.net", "http://ipsquad.net");
	myAboutData->addAuthor("Pino Toscano", 0, "toscano.pino@tiscali.it");
	
	setAboutData( myAboutData );
	
	load();
	m_hideAlt->setChecked(true);
	slotHideAlternativesClicked();
}

TDEAlternatives::~TDEAlternatives()
{
	if(m_mgr) delete m_mgr;
	if(m_altList) delete m_altList;
	if(m_optionsList) delete m_optionsList;
	if(m_altTilte) delete m_altTilte;
	if(m_statusCombo) delete m_statusCombo;
	if(m_hideAlt) delete m_hideAlt;
}

void TDEAlternatives::die()
{
	delete this;
}

void TDEAlternatives::load()
{
	clearList(m_altList);
	TQPtrList<Item> *itemslist = m_mgr->getGlobalAlternativeList();
	Item *i;
	TreeItemElement *treeit;
	for(i = itemslist->first(); i; i = itemslist->next())
	{
		AltController *altcontroller = new AltController();
		treeit = new TreeItemElement(m_altList, i, altcontroller);
		
		AltsPtrList *altList = i->getAlternatives();
		Alternative *a = altList->first();
		
		AltItemElement *ael;
		
		for(; a; a=altList->next())
		{
			ael = new AltItemElement(m_optionsList, a);
			if(!m_bisRoot) ael->setEnabled(false);
			treeit->getAltController()->addAltItem(ael);
		}
    }
}




void TDEAlternatives::clearList(TDEListView* list)
{
	TQListViewItemIterator it( list );
	TQListViewItem *tmp;
	while( (tmp=it.current()) )
	{
		it++;
		list->takeItem(tmp);
	}
}


void TDEAlternatives::slotSelectAlternativesClicked(TQListViewItem *alternative)
{
	clearList(m_optionsList);
	TreeItemElement *treeItem;
	if((treeItem = dynamic_cast<TreeItemElement *>(alternative)))
	{
		Item *item = treeItem->getItem();
		
		m_altTilte->setText(treeItem->getName());
		m_statusCombo->setCurrentItem(item->getMode());
		
		AltItemList *altItemList = treeItem->getAltController()->getAltItemList();
		
		for( AltItemElement *altItem= altItemList->first(); altItem ; altItem = altItemList->next())
		{
			Alternative *a = altItem->getAlternative();
			
			TQString priority;
			priority.setNum(a->getPriority());
			
			m_optionsList->insertItem(altItem);
			
			altItem->setText( 1, priority);
			altItem->setText( 2, a->getPath());
			TQString m_small_desc = altItem->getDescription();
			
			if (!m_small_desc.isEmpty())
			{
				altItem->setText( 3, m_small_desc);
			}
			else
			{
				altItem->searchDescription();
			}
		}
	}
	m_optionsList->setSelected(m_optionsList->firstChild(), 1);
}



void TDEAlternatives::slotHideAlternativesClicked()
{
	if (m_hideAlt->isChecked ())
	{
		TQListViewItemIterator it( m_altList );
		TreeItemElement *i;
		TQListViewItem *tmp;
		while ( it.current() )
		{
			if((i = dynamic_cast<TreeItemElement *>(it.current())))
			{
				if ((i->getItem()->getAlternatives()->count()) <= 1)
				{
					tmp = it.current();
					it++;
					m_altList->takeItem(tmp);
					continue;
				}
			}
			it++;
		}
	}
	else
	{
		load();
	}
	m_altList->setSelected(m_altList->firstChild (), 1);
}


void TDEAlternatives::slotOptionClicked(TQListViewItem *option)
{
	AltItemElement *altItem;
	if((altItem = dynamic_cast<AltItemElement *>(option)))
	{
		if( !altItem->isOn())
			return;
		TreeItemElement *treeItem;
		if((treeItem = dynamic_cast<TreeItemElement *>(m_altList->selectedItem())))
		{
			treeItem->getAltController()->setBoutonOnOff(m_optionsList, altItem);
			treeItem->setChanged(true);
			emit changed(true);
		}
	}
}

void TDEAlternatives::slotAddClicked()
{
	TreeItemElement *treeItem;
	if((treeItem = dynamic_cast<TreeItemElement *>(m_altList->selectedItem())))
	{
		m_optionsList->setSelected(m_optionsList->firstChild(), 1);
		
		AltItemElement *altItem;
		if((altItem = dynamic_cast<AltItemElement *>(m_optionsList->selectedItem())))
		{
			int countSlave = altItem->getAlternative()->countSlaves();
			AddAlternatives *addAlternatives = new AddAlternatives(treeItem, this, countSlave);
			addAlternatives->show();
		}
	}
}
void TDEAlternatives::slotDeleteClicked()
{
	TreeItemElement *treeItem;
	if((treeItem = dynamic_cast<TreeItemElement *>(m_altList->selectedItem())))
	{
		AltItemElement *altItem;
		if((altItem = dynamic_cast<AltItemElement *>(m_optionsList->selectedItem())))
		{
			treeItem->getItem()->delAlternativeByPath(altItem->getPath());
			
			AltItemList *altItemList = treeItem->getAltController()->getAltItemList();
			
			altItemList->remove(altItem);
			m_optionsList->takeItem(altItem);
			
			treeItem->setNbrAltChanged(true);
			emit changed( true );
			m_optionsList->setSelected(m_optionsList->firstChild (), 1);
		}
	}
}

void TDEAlternatives::slotPropertiesClicked()
{
	AltItemElement *altItem;
	
	if((altItem = dynamic_cast<AltItemElement *>(m_optionsList->selectedItem())))
	{
		TQString text;
		PropertiesWindow *prop = new PropertiesWindow(this);
		prop->bClose->setGuiItem(KStdGuiItem::close());
		
		Alternative *a = altItem->getAlternative();
		

		text += i18n( "Description :\n%1\n" ).arg( altItem->getDescription() );
		text += i18n( "Path : %1\n" ).arg( a->getPath() );
		text += i18n( "Priority : %1\n" ).arg( a->getPriority() );
		
		TQStringList* slavesList = a->getSlaves();
		text += i18n( "Slave :", "Slaves :", slavesList->count() );
		
		for ( TQStringList::Iterator it = slavesList->begin(); it != slavesList->end(); ++it ) 
		{
			text += "\n\t";
			text += *it;
		}
		prop->m_text->setText(text);
		prop->show();
	}
}


void TDEAlternatives::save()
{
	TQListViewItemIterator it( m_altList );
	TreeItemElement *treeItem;
	
	while ( it.current() )
	{
		if((treeItem = dynamic_cast<TreeItemElement *>(it.current())))
		{
			if(treeItem->isNbrAltChanged())
			{
				TQString parentPath =  TQString("%1/%2")
										.arg(m_mgr->getAltDir())
										.arg(treeItem->getName());
				
				TQFile origFile(parentPath);
				if(origFile.exists())
				{
					origFile.remove();
				}
				
				if( origFile.open( IO_WriteOnly )) 
				{
					TQTextStream stream( &origFile );
				
				
					Item *item = treeItem->getItem();
				
					stream << item->getMode() << endl;
					stream << item->getPath() << endl;
					
					SlaveList *slaveList = item->getSlaves();
					Slave *slave = slaveList->first();
					for(; slave; slave = slaveList->next())
					{
						stream << slave->slname << endl;
						stream << slave->slpath << endl;
					}
					
					stream << endl;
					
					AltItemList *altItemList = treeItem->getAltController()->getAltItemList();
					AltItemElement *altItem= altItemList->first();
					for( ; altItem ; altItem = altItemList->next())
					{
						Alternative *a = altItem->getAlternative();
						
						stream << a->getPath() << endl;
						stream << a->getPriority() << endl;
					
						TQStringList *slaveList = a->getSlaves();
						TQStringList::Iterator it = slaveList->begin();
						for ( ; it != slaveList->end(); ++it )
						{
							stream << *it << endl;
						}
					}
					origFile.close();
				}
				treeItem->setNbrAltChanged(false);
			}
			if(treeItem->isChanged())
			{
				AltItemList *altItemList = treeItem->getAltController()->getAltItemList();
				AltItemElement *altItem= altItemList->first();
				for( ; altItem ; altItem = altItemList->next())
				{
					if( altItem->isOn() )
					{
						Alternative *a = altItem->getAlternative();
						if(!a->select())
						{
							kdDebug() << a->getSelectError() << endl;
						}
					}
				}
				treeItem->setChanged(false);
			}
		}
		it++;
	}
	emit changed( false );
}


void TDEAlternatives::configChanged()
{
	emit changed(true);
}


TQString TDEAlternatives::quickHelp() const
{
	return i18n("<h1>TDEAlternatives</h1>\n"
	            "RPM/DPKG alternatives manager for TDE");
}



#include "tdealternatives.moc"
