/*
	msettingsdialog.cpp - A settings dialog
	Copyright (C) 2003  Konrad Twardowski <kdtonline@poczta.onet.pl>

	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 "extras.h"
#include "links.h"
#include "mactioneditdialog.h"
#include "miscutils.h"
#include "mmessagedialog.h"
#include "msettingsdialog.h"
#include "msystemtray.h"
#include "mtip.h"
#include "systemconfig.h"

#include <tqcheckbox.h>
#include <tqfile.h>
#include <tqhbox.h>
#include <tqhbuttongroup.h>
#include <tqheader.h>
#include <tqlabel.h>
#include <tqlayout.h>
#include <tqradiobutton.h>
#include <tqtooltip.h>
#include <tqvgroupbox.h>
#include <tqwhatsthis.h>

#include <tdeconfigdialogmanager.h>
#include <kiconloader.h>
#include <klineedit.h>
#include <tdelistview.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <tdepopupmenu.h>
#include <knuminput.h>
#include <kpushbutton.h>
#include <kstandarddirs.h>
#include <ktabwidget.h>
#include <kurllabel.h>

int MSettingsDialog::_lastPage = 0;
MSettingsDialog *MSettingsDialog::_instance = 0;

// public

MSettingsDialog::MSettingsDialog(TQWidget *parent)
	: KDialogBase(
		IconList,
		i18n("Settings"),
		Apply | Cancel | Default | Ok,
		Ok, // default button
		parent,
		"MSettingsDialog",
		true, // modal
		true // separator
	)
{
	_instance = this;

	initGeneralPage();
	initMessagesPage();
	initActionsPage();
	initAdvancedPage();

	_configDialogManager = new TDEConfigDialogManager(this, kshutdownrc);
	_configDialogManager->updateWidgets();
	connect(_configDialogManager, SIGNAL(widgetModified()), SLOT(slotConfigChanged()));

	connect(this, SIGNAL(applyClicked()), SLOT(slotOKClicked()));
	connect(this, SIGNAL(okClicked()), SLOT(slotOKClicked()));

	// lock after login
	c_autoLock->setChecked(TQFile::exists(TDEGlobalSettings::autostartPath() + "/kshutdown-autolock.desktop"));

	setInitialSize(configDialogSize("Settings Dialog"));
	showPage(_lastPage); // restore last page

	exec();
}

MSettingsDialog::~MSettingsDialog()
{
	_lastPage = activePageIndex(); // remember last page
}

// private

TQFrame *MSettingsDialog::addPage(const TQString &itemName, const TQString &iconName)
{
	return KDialogBase::addPage(itemName, TQString::null, MainBarIcon(iconName, 32));
}

bool MSettingsDialog::disabledByAdmin(const TQString &key, TQFrame *page,
	TQBoxLayout *pageLayout) const
{
	if (MiscUtils::isRestricted("settings_" + key))
	{
		// add tip
		if (page)
		{
			MTip *t_admin = new MTip(MTip::Info, page);
			t_admin->setTipText(i18n("Disabled by the Administrator."));
			pageLayout->addWidget(t_admin);
		}

		return true; // disabled
	}

	return false; // enabled
}

void MSettingsDialog::initActionsPage()
{
	_actionsPage = addPage(i18n("Actions"), "kshutdown");
	TQVBoxLayout *l = new TQVBoxLayout(_actionsPage, 5);

	if (disabledByAdmin("actions", _actionsPage, l))
		return;

	TQVGroupBox *gb_general = new TQVGroupBox(i18n("Actions"), _actionsPage);

	_actions = new TDEListView(gb_general, "TDEListView::_actions");
	_actions->setAllColumnsShowFocus(true);
	_actions->setItemMargin(5);
	_actions->setMaximumHeight(200);
	_actions->setSorting(-1); // no sort
	_actions->addColumn(i18n("Action"));
	_actions->addColumn(i18n("Method"));
	_actions->addColumn(i18n("Command before action"));
	_actions->header()->setClickEnabled(false);

	_logoutItem = new TDEListViewItem(_actions, ks_actions->getName(Action::Logout));
	_logoutItem->setPixmap(0, ks_actions->getIcon(Action::Logout));

	_lockScreenItem = new TDEListViewItem(_actions, ks_actions->getName(Action::LockScreen));
	_lockScreenItem->setPixmap(0, ks_actions->getIcon(Action::LockScreen));

	_rebootItem = new TDEListViewItem(_actions, ks_actions->getName(Action::Reboot));
	_rebootItem->setPixmap(0, ks_actions->getIcon(Action::Reboot));

	_shutDownItem = new TDEListViewItem(_actions, ks_actions->getName(Action::ShutDown));
	_shutDownItem->setPixmap(0, ks_actions->getIcon(Action::ShutDown));

	connect(_actions, SIGNAL(doubleClicked(TQListViewItem *, const TQPoint &, int)), SLOT(slotEditAction()));
	connect(_actions, SIGNAL(spacePressed(TQListViewItem *)), SLOT(slotEditAction()));
	// edit action
	KPushButton *b_editAction = new KPushButton(SmallIcon("edit"), i18n("Edit..."), gb_general, "KPushButton::b_editAction");
	connect(b_editAction, SIGNAL(clicked()), SLOT(slotEditAction()));
	// check system configuration
	KPushButton *b_checkSystemConfig = new KPushButton(SmallIcon("button_ok"), i18n("Check System Configuration"), gb_general, "KPushButton::b_checkSystemConfig");
	connect(b_checkSystemConfig, SIGNAL(clicked()), SLOT(slotCheckSystemConfig()));

	TQVGroupBox *gb_extras = new TQVGroupBox(i18n("Extras Menu"), _actionsPage);
	KPushButton *b_modifyExtras = new KPushButton(SmallIcon("edit"), i18n("Modify..."), gb_extras, "KPushButton::b_modifyExtras");
	if (!ks_actions->isEnabled(Action::Extras))
		gb_extras->hide();
	connect(
		b_modifyExtras, SIGNAL(clicked()),
		ks_extras, SLOT(slotModify()));

	l->addWidget(gb_general);
	l->addStretch();
	l->addWidget(gb_extras);

	// update items after widgets init
	updateActions();
}

void MSettingsDialog::initAdvancedPage()
{
	_advancedPage = addPage(i18n("Advanced"), "misc");
	TQVBoxLayout *l = new TQVBoxLayout(_advancedPage, 5);

	// after login
	TQVGroupBox *gb_afterLogin = new TQVGroupBox(i18n("After Login"), _advancedPage);
	c_autoLock = new TQCheckBox(i18n("Lock screen"), gb_afterLogin);
	connect(c_autoLock, SIGNAL(clicked()), SLOT(slotConfigChanged()));

	// cd tray close
	TQVGroupBox *gb_cdTrayClose = new TQVGroupBox(i18n("Before Logout"), _advancedPage);
	TQCheckBox *c_cdTrayClose = new TQCheckBox(i18n("Close CD-ROM Tray"), gb_cdTrayClose, "kcfg_cd_tray_close");
	TQHBox *cdTrayCloseBox = new TQHBox(gb_cdTrayClose);
	TQLabel *l_cdTrayCloseCommand = new TQLabel(i18n("Command:"), cdTrayCloseBox);
// FIXME: 2.0: disable "in_cdTrayCloseCommand" if "c_cdTrayClose" is not checked
// TODO: 2.0: "Test" button
	KLineEdit *in_cdTrayCloseCommand = new KLineEdit(cdTrayCloseBox, "kcfg_cd_tray_close_command");
	l_cdTrayCloseCommand->setBuddy(in_cdTrayCloseCommand);
	connect(
		c_cdTrayClose, SIGNAL(toggled(bool)),
		in_cdTrayCloseCommand, SLOT(setEnabled(bool)));

	// kde settings
	KPushButton *b_kdeSettings = new KPushButton(SmallIcon("misc"), i18n("Related TDE Settings..."), _advancedPage, "KPushButton::b_kdeSettings");
	connect(b_kdeSettings, SIGNAL(clicked()), SLOT(slotKDESettings()));

	l->addWidget(gb_afterLogin);
	l->addWidget(gb_cdTrayClose);
	l->addStretch();
	l->addWidget(b_kdeSettings);
}

void MSettingsDialog::initGeneralPage()
{
	_generalPage = addPage(i18n("General"), "misc");
	TQVBoxLayout *l = new TQVBoxLayout(_generalPage, 5);

	// problems
	TQVGroupBox *gb_problems = new TQVGroupBox(i18n("Common Problems"), _generalPage);

	KURLLabel *ul_shutDownProblem = new KURLLabel(gb_problems);
	ul_shutDownProblem->setText(i18n("\"Turn Off Computer\" does not work"));
	connect(ul_shutDownProblem, SIGNAL(leftClickedURL()), SLOT(slotShutDownProblem()));

	KURLLabel *ul_trayMessageProblem = new KURLLabel(gb_problems);
	ul_trayMessageProblem->setText(i18n("Popup messages are very annoying"));
	connect(ul_trayMessageProblem, SIGNAL(leftClickedURL()), SLOT(slotTrayMessageProblem()));

	// links
	TQVGroupBox *gb_links = new TQVGroupBox(i18n("Add/Remove Links"), _generalPage);
	new Links(gb_links);

	// system tray
	gb_systemTray = new TQHButtonGroup(i18n("Show System Tray Icon"), _generalPage, "kcfg_system_tray");
	TQRadioButton *rb_systemTray;
	rb_systemTray = new TQRadioButton(i18n("Always"), gb_systemTray);
	MiscUtils::setHint(rb_systemTray, i18n("Tray icon will be always visible."));
	rb_systemTray = new TQRadioButton(i18n("If Active"), gb_systemTray);
	MiscUtils::setHint(rb_systemTray, i18n("Tray icon will be visible only if KShutDown is active."));
	rb_systemTray = new TQRadioButton(i18n("Never"), gb_systemTray);
	MiscUtils::setHint(rb_systemTray, i18n("Tray icon will be always hidden."));

	l->addWidget(gb_problems);
	l->addWidget(gb_links);
	l->addWidget(gb_systemTray);

	// karamba info
	TQString karambaThemes = locate("appdata", "karamba/kshutdown-48x48.png");
	if (!karambaThemes.isNull())
	{
		int i = karambaThemes.findRev("/");
		if ((i != -1) && (i > 0))
		{
			MTip *t_karamba = new MTip(MTip::Info, _generalPage);
/* TODO: 2.0: superkaramba integration
			t_karamba->disconnect(
				t_karamba, SIGNAL(linkClicked(const TQString &)),
				t_karamba, SLOT(openLink(const TQString &))
			);
			t_karamba->connect(
				t_karamba, SIGNAL(linkClicked(const TQString &)),
				this, SLOT(slotOpenKarambaLink(const TQString &))
			);
*/
			karambaThemes = karambaThemes.left(i);
			t_karamba->setTipText(
				// title
				"<h2>SuperKaramba</h2>" \
				// themes
				"<a href=\"" + karambaThemes + "\">" + i18n("Show KShutDown Themes") + "</a><br>" \
				// home page
				"<a href=\"http://www.superkaramba.com/index.php\">" + i18n("SuperKaramba Home Page") + "</a>" \
			);
			l->addWidget(t_karamba);
		}
	}
}

void MSettingsDialog::initMessagesPage()
{
	_messagesPage = addPage(i18n("Messages"), "messagebox_warning");
	TQVBoxLayout *l = new TQVBoxLayout(_messagesPage, 5);

	KTabWidget *t_messages = new KTabWidget(_messagesPage);
	t_messages->setFocusPolicy(StrongFocus);

	// warning message:
	TQWidget *w_warning = new TQWidget(_messagesPage);
	TQVBoxLayout *l_warning = new TQVBoxLayout(w_warning, 5);
	// enabled/info
	TQCheckBox *c_warningMessageEnabled = new TQCheckBox(i18n("Display a warning message before action"), w_warning, "kcfg_warning_message_enabled");
	// slider
	in_warningMessageDelay = new KIntNumInput(w_warning, "kcfg_warning_message_delay");
	in_warningMessageDelay->setSuffix(" " + i18n("minute(s)"));
	in_warningMessageDelay->setRange(1, 60, 1, true);
	KPushButton *b_warningMessageTest = new KPushButton(KStdGuiItem::test(), w_warning, "KPushButton::b_warningMessageTest");
	connect(b_warningMessageTest, SIGNAL(clicked()), SLOT(slotWarningMessageTest()));

	TQLabel *l_warningText = new TQLabel(i18n("Recommended"), w_warning);
	l_warningText->setFont(TQFont(l_warningText->font().family(), l_warningText->font().pointSize(), TQFont::Bold));
	l_warning->addWidget(l_warningText);

	l_warning->addWidget(c_warningMessageEnabled);

	l_warning->addWidget(in_warningMessageDelay);
	l_warning->addStretch();
	l_warning->addWidget(b_warningMessageTest);
	t_messages->addTab(w_warning, i18n("Warning Message"));

	// custom message:
	TQWidget *w_customMessage = new TQWidget(_messagesPage);
	TQVBoxLayout *l_customMessage = new TQVBoxLayout(w_customMessage, 5);
	TQCheckBox *c_customMessageEnabled = new TQCheckBox(i18n("Enabled"), w_customMessage, "kcfg_custom_message_enabled");
	TQLabel *l_customMessageCommand = new TQLabel(i18n("A shell command to execute:"), w_customMessage);
	in_customMessageCommand = new KLineEdit(w_customMessage, "kcfg_custom_message_command");
	MiscUtils::setHint(
		in_customMessageCommand,
		MiscUtils::HTML(
			i18n("Enter a command.") +
			"<ul>" \
				"<li><b>%appname</b> KShutDown</li>" \
				"<li><b>%text</b> " + i18n("A message text") + "</li>" \
				"<li><b>%title</b> " + i18n("The current main window title") + "</li>" \
			"</ul>"
		)
	);
	l_customMessageCommand->setBuddy(in_customMessageCommand);

	KPushButton *b_customMessagePresets = new KPushButton(i18n("Presets"), w_customMessage, "KPushButton::b_customMessagePresets");
	TDEPopupMenu *pm_customMessagePresets = new TDEPopupMenu(b_customMessagePresets);
	pm_customMessagePresets->insertItem("KDialog", this, SLOT(slotSetKDialogCustomMessage()));
	pm_customMessagePresets->insertItem("Amor", this, SLOT(slotSetAmorCustomMessage()));
	b_customMessagePresets->setPopup(pm_customMessagePresets);

	KPushButton *b_testCustomMessage = new KPushButton(KStdGuiItem::test(), w_customMessage, "KPushButton::b_testCustomMessage");
	connect(b_testCustomMessage, SIGNAL(clicked()), SLOT(slotCustomMessageTest()));
	l_customMessage->addWidget(c_customMessageEnabled);
	l_customMessage->addWidget(l_customMessageCommand);
	l_customMessage->addWidget(in_customMessageCommand);
	l_customMessage->addWidget(b_customMessagePresets);
	l_customMessage->addStretch();
	l_customMessage->addWidget(b_testCustomMessage);
	t_messages->addTab(w_customMessage, i18n("Custom Message"));

	// progress bar
	TQVGroupBox *w_progressBar = new TQVGroupBox(i18n("Progress Bar"), _messagesPage);
	new TQCheckBox(i18n("Enabled"), w_progressBar, "kcfg_progress_bar_enabled");

	// re-enable messages
	b_enableAllMessages = new KPushButton(i18n("Re-enable All Message Boxes"), _messagesPage, "KPushButton::b_enableAllMessages");
	MiscUtils::setHint(
		b_enableAllMessages,
		MiscUtils::HTML(i18n(
			"Enable all messages which have been turned off with the " \
			"<b>Do not show this message again</b> feature."
		))
	);
	connect(b_enableAllMessages, SIGNAL(clicked()), SLOT(slotEnableAllMessages()));

	l->addWidget(t_messages);
	l->addWidget(w_progressBar);
	l->addStretch();
	l->addWidget(b_enableAllMessages);

	connect(
		c_warningMessageEnabled, SIGNAL(toggled(bool)),
		in_warningMessageDelay, SLOT(setEnabled(bool)));
	connect(
		c_warningMessageEnabled, SIGNAL(toggled(bool)),
		b_warningMessageTest, SLOT(setEnabled(bool)));
	connect(
		c_customMessageEnabled, SIGNAL(toggled(bool)),
		in_customMessageCommand, SLOT(setEnabled(bool)));
	connect(
		c_customMessageEnabled, SIGNAL(toggled(bool)),
		b_customMessagePresets, SLOT(setEnabled(bool)));
	connect(
		c_customMessageEnabled, SIGNAL(toggled(bool)),
		b_testCustomMessage, SLOT(setEnabled(bool)));
}

Action::Type MSettingsDialog::itemToActionType(const TDEListViewItem *item) const
{
	if (!item)
		return Action::Nothing;

	if (item == _lockScreenItem)
		return Action::LockScreen;

	if (item == _logoutItem)
		return Action::Logout;

	if (item == _rebootItem)
		return Action::Reboot;

	if (item == _shutDownItem)
		return Action::ShutDown;

	return Action::Nothing;
}

void MSettingsDialog::updateActions()
{
	updateItem(_shutDownItem);
	updateItem(_rebootItem);
	updateItem(_lockScreenItem);
	updateItem(_logoutItem);
	_actions->setCurrentItem(_shutDownItem);
}

void MSettingsDialog::updateItem(TDEListViewItem *item)
{
	Action::Type action = itemToActionType(item);

	if (action == Action::Nothing)
		return;

	Action::Method method = Action::Method_TDE;
	TQString
		command,
		group = ks_actions->actionToConfigGroup(action);

	ks_actions->getMethod(action, method, command);

	// method
	if (method == Action::Method_TDE)
		item->setText(1, i18n("TDE (default)"));
	else
		item->setText(1, command);

	// command before action
	if (!group.isNull())
	{
		TDEConfig *conf = kshutdownrc->config();
		conf->setGroup(group);
		if (conf->readBoolEntry("RunCommandBeforeAction", false))
		{
			TQString cmd = conf->readEntry("CommandBeforeAction", "");
			int pause = conf->readNumEntry("CommandBeforeActionPause", 10);
			if (pause == 0)
				cmd += " [" + i18n("No pause") + "]";
			else
				cmd += " [" + i18n("Pause: %1").arg(TQString::number(pause) + "s") + "]";
			item->setText(2, cmd);
		}
		else
		{
			item->setText(2, "");
		}
	}
}

// private slots

void MSettingsDialog::slotCheckSystemConfig()
{
	SystemConfig::check(this);
}

void MSettingsDialog::slotConfigChanged()
{
	actionButton(Apply)->setEnabled(_configDialogManager->hasChanged());
}

void MSettingsDialog::slotCustomMessageTest()
{
	MiscUtils::customMessage(i18n("Test"), in_customMessageCommand->text());
}

void MSettingsDialog::slotEditAction()
{
	TDEListViewItem *item = static_cast<TDEListViewItem *>(_actions->currentItem());

	if (!item)
		return;

	MActionEditDialog *dialog = new MActionEditDialog(this, itemToActionType(item));
	if (dialog->exec() == TQDialog::Accepted)
	{
		updateItem(item);
		slotConfigChanged();
	}
	delete dialog;
}

void MSettingsDialog::slotEnableAllMessages()
{
	KMessageBox::enableAllMessages();
	b_enableAllMessages->setEnabled(false);
}

void MSettingsDialog::slotKDESettings()
{
	MiscUtils::runCommand("tdecmshell screensaver kcmsmserver tdm");
}

void MSettingsDialog::slotOKClicked()
{
	saveDialogSize("Settings Dialog");
	_configDialogManager->updateSettings();

// FIXME: 2.0: apply button

	// lock after login
	if (c_autoLock->isChecked())
	{
		Links::createLink(
			TDEGlobalSettings::autostartPath() + "/kshutdown-autolock.desktop",
			"kshutdown --init --lock",
			"kshutdown",
			"KShutDown",
			i18n("This file is used to lock session at TDE startup")
		);
	}
	else
	{
		Links::removeLink(TDEGlobalSettings::autostartPath() + "/kshutdown-autolock.desktop");
	}

	int id = gb_systemTray->selectedId();
	if (id != -1)
		MSystemTray::setMode((MSystemTray::Mode)id);

	kshutdownrc->writeConfig();

	slotConfigChanged();
}

// TODO: 2.0: remember last page

void MSettingsDialog::slotSetAmorCustomMessage() {
	in_customMessageCommand->setText(KS_CONFIG_AMOR_MESSAGE);
}

void MSettingsDialog::slotSetKDialogCustomMessage() {
	in_customMessageCommand->setText(KS_CONFIG_KDIALOG_MESSAGE);
}

void MSettingsDialog::slotShutDownProblem()
{
	showPage(pageIndex(_actionsPage));
}

void MSettingsDialog::slotTrayMessageProblem()
{
	showPage(pageIndex(_messagesPage));
}

void MSettingsDialog::slotWarningMessageTest()
{
	MMessageDialog *messageDialog = new MMessageDialog(
		in_warningMessageDelay->value() * 60,
		Action::Nothing,
		i18n("Test")
	);
	messageDialog->exec();
	delete messageDialog;
}

// protected slots

void MSettingsDialog::slotDefault()
{
	int index = activePageIndex();

	if (index == -1)
		return;

	_configDialogManager->updateSettings();

	// general
	if (index == pageIndex(_generalPage))
	{
		kshutdownrc->i_systemTray->setDefault();
	}
	// messages
	else if (index == pageIndex(_messagesPage))
	{
		kshutdownrc->i_warningMessageEnabled->setDefault();
		kshutdownrc->i_warningMessageDelay->setDefault();
		kshutdownrc->i_customMessageEnabled->setDefault();
		kshutdownrc->i_customMessageCommand->setDefault();
	}
	// actions
	else if (index == pageIndex(_actionsPage))
	{
		if (disabledByAdmin("actions"))
			return;

		if (KMessageBox::warningYesNo(
			0,
			i18n("Restore default settings for this page?"),
			caption()) != KMessageBox::Yes
		)
			return;

		TDEConfig *conf = kshutdownrc->config();
		conf->deleteGroup("Shut Down");
		conf->deleteGroup("Reboot");
		conf->deleteGroup("Lock Screen");
		conf->deleteGroup("Logout");
		updateActions();
		slotConfigChanged();
	}
	// advanced
	else if (index == pageIndex(_advancedPage))
	{
		c_autoLock->setChecked(false);
		kshutdownrc->i_cdTrayClose->setDefault();
		kshutdownrc->i_cdTrayCloseCommand->setDefault();
		slotConfigChanged();
	}
	else
	{
		return;
	}
	_configDialogManager->updateWidgets();
}
#include "msettingsdialog.moc"
