/***************************************************************************
 *   Copyright (C) 2005-2008 by Eugene V. Lyubimkin aka jackyf             *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License                  *
 *   (version 3 or above) as published by the Free Software Foundation.    *
 *                                                                         *
 *   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 GPL                        *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA               *
 ***************************************************************************/
#include <QApplication>
#include <QMessageBox>
#include <QInputDialog>
#include <QListWidget>
#include <QTabWidget>
#include <QLineEdit>
#include <QTextEdit>
#include <QComboBox>
#include <QString>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QPushButton>
#include <QLabel>
#include <QDir>
#include <QTextStream>
#include <QDialogButtonBox>

#include "ProfileManager.hpp"
#include "Setup.hpp"
#include "UserProfile.hpp"

const QString profileFileExtension = ".v2";

ProfileManager::ProfileManager(QString& profile)
	: profile(profile)
{
	readGuiSettings();

	// ok & cancel buttons
	this->okButton = new QPushButton(tr("Select"));
	this->okButton->setDefault(true);
	this->okButton->setShortcut(QKeySequence(Qt::Key_Return));
	connect(this->okButton, SIGNAL(clicked()), this, SLOT(selectProfile()));

	this->cancelButton = new QPushButton(tr("Cancel"));
	this->cancelButton->setShortcut(QKeySequence(Qt::Key_Escape));
	connect(this->cancelButton, SIGNAL(clicked()), this, SLOT(quit()));

	QDialogButtonBox* bottomButtonsBox = new QDialogButtonBox(Qt::Horizontal);
	bottomButtonsBox->addButton(this->okButton, QDialogButtonBox::AcceptRole);
	bottomButtonsBox->addButton(this->cancelButton, QDialogButtonBox::RejectRole);

	// "use existing" part
	this->existingProfilesList = new QListWidget;
	this->profileTipWidget = new QTextEdit;
	this->profileTipWidget->setAcceptRichText(true);
	this->profileTipWidget->setReadOnly(true);

	deleteProfileButton = new QPushButton(tr("Delete"));
	connect(deleteProfileButton, SIGNAL(clicked()), this, SLOT(deleteSelectedProfile()));

	renameProfileButton = new QPushButton(tr("Rename"));
	connect(renameProfileButton, SIGNAL(clicked()), this, SLOT(renameSelectedProfile()));

	QHBoxLayout* useExistingProfileWidgetLeftBottomLayout = new QHBoxLayout;
	useExistingProfileWidgetLeftBottomLayout->addWidget(renameProfileButton);
	useExistingProfileWidgetLeftBottomLayout->addWidget(deleteProfileButton);

	QVBoxLayout* useExistingProfileLeftWidgetLayout = new QVBoxLayout;
	useExistingProfileLeftWidgetLayout->addWidget(this->existingProfilesList);
	useExistingProfileLeftWidgetLayout->addLayout(useExistingProfileWidgetLeftBottomLayout);

	QHBoxLayout* useExistingProfileWidgetLayout = new QHBoxLayout;
	useExistingProfileWidgetLayout->addLayout(useExistingProfileLeftWidgetLayout, 3);
	useExistingProfileWidgetLayout->addWidget(this->profileTipWidget, 5);

	QWidget* useExistingProfileWidget = new QWidget;
	useExistingProfileWidget->setLayout(useExistingProfileWidgetLayout);

	// "create new" part
	QWidget* useNewProfileWidget = new QWidget;

	this->layoutsCombo = new QComboBox;
	this->loadLayoutsList();

	this->newProfileName = new QLineEdit();

	QLabel* newProfileNameLabel = new QLabel(tr("Enter name of new profile:"));
	newProfileNameLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);

	QLabel* newProfileSelectLayoutLabel = new QLabel(tr("Select the layout:"));
	//newProfileSelectLayoutLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);

	QGridLayout* useNewProfileWidgetLayout = new QGridLayout;
	useNewProfileWidgetLayout->addWidget(newProfileNameLabel, 0, 0);
	useNewProfileWidgetLayout->addWidget(this->newProfileName, 0, 1);
	useNewProfileWidgetLayout->addWidget(newProfileSelectLayoutLabel, 1, 0);
	useNewProfileWidgetLayout->addWidget(this->layoutsCombo, 1, 1);

	useNewProfileWidget->setLayout(useNewProfileWidgetLayout);

	// misc
	this->tabs = new QTabWidget;
	this->tabs->addTab(useExistingProfileWidget, tr("Existing profile"));
	this->tabs->addTab(useNewProfileWidget, tr("New profile"));
	this->setWindowTitle(tr("Select the profile"));

	QVBoxLayout* layout = new QVBoxLayout;
	layout->addWidget(this->tabs);
	layout->addWidget(bottomButtonsBox);
	this->setLayout(layout);

	this->loadExistingProfilesList();
	connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(renewOkButtonEnabled()));
	connect(this->existingProfilesList, SIGNAL(currentRowChanged(int)), this, SLOT(displayTip(int)));
}

void ProfileManager::loadExistingProfilesList()
{
	QSettings settings;

	QDir profileDir = pathToUserProfiles;
	this->existingProfilesList->clear();
	this->profileTips.clear();
	QStringList profilesList = profileDir.entryList((QStringList() << ("*" + profileFileExtension)), QDir::Files);
	foreach (const QString profileName, profilesList)
	{
		QString profilePath = pathToUserProfiles + profileName;
		if (UserProfile::isCorrectProfile(profilePath))
		{
			this->existingProfilesList->addItem(profileName);

			// building the tip info for profile
			UserProfile profileInfo(profilePath);

			this->profileTips.push_back(profileInfo.getGeneralStats());
		}
		else
		{
			qWarning("Skipped the profile %s.", qPrintable(profileName));
		}
	}

	// selecting last used profile if available
	settings.beginGroup("ProfileManager");
	QString lastProfileName = settings.value("last_used_profile", QString::fromLatin1("default")).toString();
	settings.endGroup();

	if (!this->existingProfilesList->findItems(lastProfileName, Qt::MatchFixedString | Qt::MatchCaseSensitive).empty())
	{
		for (int i = 0; i < this->existingProfilesList->count(); ++i)
		{
			if (this->existingProfilesList->item(i)->text() == lastProfileName)
			{
				this->existingProfilesList->setCurrentRow(i);
			}
		}
	}
	else if (this->existingProfilesList->count())
	{
		this->existingProfilesList->setCurrentRow(0);
	}
	else
	{
		this->renameProfileButton->setEnabled(false);
		this->deleteProfileButton->setEnabled(false);
		this->renewOkButtonEnabled();
	}
	this->displayTip(this->existingProfilesList->currentRow());
}
void ProfileManager::loadLayoutsList()
{
	QDir layoutsDir = pathToLayouts;
	QStringList layoutsList = layoutsDir.entryList(QDir::Files);
	foreach (const QString layoutName, layoutsList)
	{
		this->layoutsCombo->addItem(layoutName);
	}

	if (this->layoutsCombo->count())
	{
		this->layoutsCombo->setCurrentIndex(0);
	}
	else
	{
		qFatal("Unable to find any layouts in %s", qPrintable(pathToLayouts));
	}
}

void ProfileManager::selectProfile()
{
	QSettings settings;

	if (tabs->currentIndex() == 0) // use existing profile tab
	{
		profile = this->existingProfilesList->item(this->existingProfilesList->currentRow())->text();
	}
	else // use new profile name
	{
		QString newProfileName = this->newProfileName->text() + profileFileExtension;
		enum UserProfile::ConstructNewProfileResult constructResult = UserProfile::constructNewProfile(
				newProfileName,
				this->layoutsCombo->currentText());

		switch (constructResult)
		{
			case UserProfile::ProfileExists:
				QMessageBox::critical(this, tr("Cannot use this profile name"),
						tr("The profile with name '%1' already exists.").arg(newProfileName));
				return;
			case UserProfile::CombinationError:
				QMessageBox::critical(this, tr("Cannot use this profile name"),
						tr("Cannot open default configuration for selected layout."));
				return;
			case UserProfile::OtherError:
				QMessageBox::critical(this, tr("Cannot use this profile name"),
						tr("Unknown error occured."));
				return;
			case UserProfile::Ok:
				; // everything is ok
		}

		this->profile = newProfileName;
	}
	// saving which profile selected (if selected :))
	if (this->profile != QString())
	{
		settings.beginGroup("ProfileManager");
		settings.setValue("last_used_profile", this->profile);
		settings.endGroup();
	}
	this->quit();
}

void ProfileManager::writeGuiSettings()
{
	QSettings settings;

	settings.beginGroup("ProfileManager");
	settings.setValue("pos", pos());
	settings.setValue("size", size());
	settings.endGroup();
}

void ProfileManager::readGuiSettings()
{
	QSettings settings;

	settings.beginGroup("ProfileManager");
	resize(settings.value("size", QSize(150, 100)).toSize());
	move(settings.value("pos", QPoint(200, 200)).toPoint());
	settings.endGroup();
}

void ProfileManager::quit()
{
	writeGuiSettings();
	qApp->quit();
}

void ProfileManager::deleteSelectedProfile()
{
	QString selectedProfile = this->existingProfilesList->item(this->existingProfilesList->currentRow())->text();

	QMessageBox::StandardButton answer = QMessageBox::question(this, tr("Delete profile?"),
		tr("Do you really want to delete the profile '%1'?").arg(selectedProfile),
		QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel);

	if (answer == QMessageBox::Ok)
	{
		bool success = QFile::remove(pathToUserProfiles + selectedProfile);

		if (!success)
		{
			QMessageBox::critical(this, tr("Unable to delete the profile"),
				tr("Somewhy cannot delete the profile '%1' :(").arg(selectedProfile));
		}

		this->loadExistingProfilesList();
	}
}

void ProfileManager::renameSelectedProfile()
{
	QString selectedProfile = this->existingProfilesList->item(this->existingProfilesList->currentRow())->text();

	bool ok;

	QString newName = QInputDialog::getText(this, tr("Renaming profile"),
		tr("Enter the new profile for profile '%1':").arg(selectedProfile),
		QLineEdit::Normal, selectedProfile, &ok);

	if (ok)
	{
		bool success = QFile::rename(pathToUserProfiles + selectedProfile,
			pathToUserProfiles + newName);

		if (!success)
		{
			QMessageBox::critical(this, tr("Unable to rename the profile"),
				tr("Somewhy cannot rename the profile '%1' :(").arg(selectedProfile));
		}

		this->loadExistingProfilesList();
	}
}

void ProfileManager::renewOkButtonEnabled()
{
	if (tabs->currentIndex() == 0)
	{
		if (!this->existingProfilesList->count())
		{
			this->okButton->setEnabled(false);
		}
		else
		{
			this->okButton->setEnabled(true);
		}
	}
	else
	{
		this->okButton->setEnabled(true);
	}
}

void ProfileManager::displayTip(int currentRow)
{
	if (currentRow != -1) // if there is at least one profile
	{
		this->profileTipWidget->setHtml(this->profileTips[currentRow]);
	}
	else
	{
		this->profileTipWidget->setHtml(QString());
	}
}

