/***************************************************************************
 *   Copyright (C) 2004 by David Sansome                                   *
 *   me@davidsansome.com                                                   *
 *                                                                         *
 *   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 "uninstallwizard.h"
#include "headerlistitem.h"
#include "data.h"

#include <qregexp.h>
#include <qwidgetstack.h>
#include <qfile.h>
#include <qtextstream.h>
#include <qheader.h>
#include <qlistbox.h>
#include <qmessagebox.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qtextedit.h>
#include <qlabel.h>

AppListItem::AppListItem(QString nN, QString n, QListView* parent)
 : QCheckListItem(parent, "", QCheckListItem::CheckBox)
{
	niceName = nN;
	name = n;
	section = 2;
	
	setText(0, niceName);
}

int AppListItem::compare(QListViewItem* i, int col, bool ascending) const
{
	switch (i->rtti())
	{
		case 1003: // App
		{
			AppListItem* item = (AppListItem*) i;
			if (section < item->section)
				return -1;
			if (section > item->section)
				return 1;
			return QListViewItem::compare(i, col, ascending);
		}
		break;
		
		case 1002: // Header
		{
			HeaderListItem* item = (HeaderListItem*) i;
			if (section < item->section)
				return -1;
			return 1;
		}
		break;
	}
	return 0;
}


UninstallWizard::UninstallWizard(QWidget* parent, const char* name, bool modal, WFlags fl)
: WizardBase(parent,name, modal,fl)
{
	mainStack->raiseWidget(1);
	setCaption("Uninstall Software");
	titleLabel->setText("<b>Uninstall Software</b>");
	componentInfo->setMaximumSize(32767,70);
	
	logDialog = new LogDialog(this);
	logDialog->hide();
	appList->header()->hide();
	
	globalHeader = NULL;
	
	icon.convertFromImage(qembed_findImage("misc"));
	
	externalProcess = new QProcess(this);
	connect(externalProcess, SIGNAL(processExited()), SLOT(processExited()));
	connect(externalProcess, SIGNAL(readyReadStdout()), SLOT(readyReadStdout()));
	connect(externalProcess, SIGNAL(readyReadStderr()), SLOT(readyReadStderr()));
	
	QFile uninstallScript("/tmp/arkollon-uninstall.sh");
	if (uninstallScript.exists())
		uninstallScript.remove();
	uninstallScript.open(IO_WriteOnly);
	QDataStream stream(&uninstallScript);
	stream.writeRawBytes((const char*)uninstaller_sh_data, uninstaller_sh_len);
	uninstallScript.close();
	
	currentStage = ListingPackages;
	externalProcess->addArgument("/bin/sh");
	externalProcess->addArgument("/tmp/arkollon-uninstall.sh");
	externalProcess->addArgument("--list");
	externalProcess->start();
}

UninstallWizard::~UninstallWizard()
{
	QFile uninstallScript("/tmp/arkollon-uninstall.sh");
	if (uninstallScript.exists())
		uninstallScript.remove();
}

void UninstallWizard::logPressed()
{
	logDialog->show();
}

void UninstallWizard::cancelPressed()
{
	reject();
}

void UninstallWizard::previousPressed()
{
	int currentId = uninstallStack->id(uninstallStack->visibleWidget());
	if (currentId == 0)
		return;
		
	uninstallStack->raiseWidget(--currentId);
	
	if (currentId == 0)
		previousButton->setEnabled(false);
	nextButton->setEnabled(true);
}

void UninstallWizard::nextPressed()
{
	int currentId = uninstallStack->id(uninstallStack->visibleWidget());
	if (currentId == 2)
	{
		accept();
		return;
	}
	
	if (currentId == 0)
	{
		bool checked = false;
		QStringList argList;
		argList.append("/bin/sh");
		argList.append("/tmp/arkollon-uninstall.sh");
		for ( QListViewItem * myChild = appList->firstChild() ; myChild != NULL ; myChild = myChild->nextSibling())
		{
			if (myChild->rtti() != 1003)
				continue;
			AppListItem* app = (AppListItem*) myChild;
			if (!app->isOn())
				continue;
			argList.append("--files");
			argList.append(app->name);
			checked = true;
		}
		if (!checked)
		{
			QMessageBox::warning(this, "Error", "You need to select at least one package to remove", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
			return;
		}
		fileList->clear();
		currentStage = ListingFiles;
		externalProcess->setArguments(argList);
		externalProcess->start();
		nextButton->setEnabled(false); // Set true again when the process is done
	}
	
	uninstallStack->raiseWidget(++currentId);
	
	if (currentId == 2)
		removeUserPackages();
	else
		previousButton->setEnabled(true);
}

void UninstallWizard::processExited()
{
	switch (currentStage)
	{
	case ListingPackages:
		if (appList->childCount() <= 0)
		{
			QMessageBox::warning(NULL, "Warning", "There are no packages installed", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
			reject();
			return;
		}
		show();
		break;
	case ListingFiles:
		nextButton->setEnabled(true);
		fileList->sort();
		break;
	case RemovingGlobal:
		finished();
		break;
	}
}

void UninstallWizard::readyReadStdout()
{
	switch (currentStage)
	{
	case ListingPackages:
	{
		while (externalProcess->canReadLineStdout())
		{
			QString line = externalProcess->readLineStdout();
			if (line.isEmpty())
				continue;
				
			// See if it already exists
			bool exists = false;
			
			for ( QListViewItem * myChild = appList->firstChild() ; myChild != NULL ; myChild = myChild->nextSibling())
			{
				if (myChild->rtti() != 1003)
					continue;
				AppListItem* app = (AppListItem*) myChild;
				if (app->name.lower() == line.lower())
				{
					exists = true;
					break;
				}
			}
			if (exists)
				continue;
			
			QString niceName = line.left(line.findRev(':'));
			niceName = niceName.left(1).upper() + niceName.right(niceName.length()-1);
			new AppListItem(niceName, line, appList);
			
			if (globalHeader == NULL)
			{
				globalHeader = new HeaderListItem(appList);
				globalHeader->setText(0, "Applications available to all users");
				globalHeader->section = 1;
			}
		}
		break;
	}
	case ListingFiles:
	{
		while (externalProcess->canReadLineStdout())
		{
			QString line = externalProcess->readLineStdout();
			if (line.isEmpty())
				continue;
			fileList->insertItem(icon, line.left(line.find("  ")));
		}
		break;
	}
	case RemovingGlobal:
		while (externalProcess->canReadLineStdout())
		{
			QString line = externalProcess->readLineStdout();
			if (line.isEmpty())
				continue;
			line.replace(QRegExp("\\033[^m]*m"), "");
			logDialog->logBox->append(line);
		}
		break;
	}
}

void UninstallWizard::readyReadStderr()
{
	while (externalProcess->canReadLineStdout())
	{
		QString line = externalProcess->readLineStdout();
		if (line.isEmpty())
			continue;
		line.replace(QRegExp("\\033[^m]*m"), "");
		logDialog->logBox->append(line);
	}
}

void UninstallWizard::removeUserPackages()
{
	nextButton->setEnabled(false); // Set true again when the process is done
	previousButton->setEnabled(false);
	
	// Find out which packages belong to the user, and uninstall them
	QStringList argList;
	argList.append("/bin/sh");
	argList.append("/tmp/arkollon-uninstall.sh");
	for ( QListViewItem * myChild = appList->firstChild() ; myChild != NULL ; myChild = myChild->nextSibling())
	{
		if (myChild->rtti() != 1003)
			continue;
		AppListItem* app = (AppListItem*) myChild;
		if (!app->isOn())
			continue;
		
		argList.append("--remove");
		argList.append(app->name);
	}
	currentStage = RemovingGlobal;
	externalProcess->setArguments(argList);
	externalProcess->start();
}

void UninstallWizard::finished()
{
	pleaseWaitLabel2->setText("Removal of packages complete!");
	nextButton->setText("Finish");
	nextButton->setEnabled(true);
}

#include "uninstallwizard.moc"

