/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
/*
Author: Christian Hubinger <chubinger@irrsinnig.org>, (C) 2001-2004
*/

#include "kmfconfigdialog.h"
#include "kmfconfigdialog.moc"

// QT includes
#include <tqstring.h>
#include <tqframe.h>
#include <tqlabel.h>
#include <tqlayout.h>
#include <tqcheckbox.h>
#include <tqradiobutton.h>
#include <tqbuttongroup.h>
#include <tqregexp.h>
#include <tqmessagebox.h>

// KDE includes
#include <kapplication.h>
#include <kdebug.h>
#include <klocale.h>
#include <kurlrequester.h>
#include <kguiitem.h>
#include <kpushbutton.h>
#include <knuminput.h>
#include <klistbox.h>
#include <kcombobox.h>
#include <kiconloader.h>
#include <kglobal.h>
#include <kmessagebox.h>
#include <klistview.h>
#include <ktrader.h>
#include <kparts/part.h>
#include <kparts/plugin.h>
#include <kparts/factory.h>


// Project includes
#include "core/kmfdoc.h"
#include "core/kmfprotocollibrary.h"
#include "core/kmfconfig.h"
#include "core/kmftarget.h"
#include "core/kmftargetconfig.h"
#include "core/kmfnetwork.h"

#include "kmfwidgets/kmfchecklistoutput.h"
#include "kmfwidgets/kmfinterfacewidget.h"
#include "kmfwidgets/kmfmynetworkwidget.h"
#include "kmfwidgets/kmfgenericinterfaceeditprotocol.h"

#include "core/kmfcompilerinterface.h"
#include "core/xmlnames.h"

namespace KMF {
KMFConfigDialog::KMFConfigDialog( TQWidget *parent, const char *name, bool modal ) : KDialogBase( IconList, i18n( "Configure" ), Ok | Apply | Cancel,
        Ok, parent, name, modal, true ) {
	loadIcons();
	
	m_backends = new TQPtrList<TQStringList>;
	setupGeneral();
	setupCustomProtocols();
	setupListView();
	setupPlugins();
	checkPlugins();
	slotReadConfig();
	setBaseSize( 800, 600 );
}

KMFConfigDialog::~KMFConfigDialog() {}

void KMFConfigDialog::setNetwork( KMFNetwork* net ) {
	m_network = net;
	m_protocolPageEditProtocol->loadDoc( net );
	m_protocolPageEditProtocol->slotUpdateView();
}

void KMFConfigDialog::slotApply() {
	kdDebug() << "void KMFConfigDialog::slotApply()" << endl;
	slotSaveConfig();
	KMFConfig::writeConfig();
	emit sigConfigChanged();
}

void KMFConfigDialog::accept() {
	kdDebug() << "void KMFConfigDialog::accept()" << endl;
	slotSaveConfig();
	KMFConfig::writeConfig();
	emit sigConfigChanged();
	TQDialog::accept();
}

void KMFConfigDialog::reject() {
	kdDebug() << "void KMFConfigDialog::reject()" << endl;
}

void KMFConfigDialog::exec() {
	TQDialog::exec();
}

void KMFConfigDialog::convertConfig() {
	kdDebug() << "void KMFConfigDialog::convertConfig()" << endl;
	const TQString & msg = i18n( "<qt><p><b>Importing installation target Settings</b><br>"
								"The settings will be applied to the <b>My Local Computer</b> Host. Remote hosts must be configureed seperately.</p></qt>" );
	if( KMessageBox::questionYesNo( this, msg ) != 3 ) {
		return;
	}
	
	
	m_network->currentTarget();
	KMFTargetConfig *conf = m_network->netzone()->findTargetByName( Constants::Localhost_Name )->config();
	conf->setOS( KMFConfig::oS().lower() );
	conf->setBackend( KMFConfig::backend().lower() );
	conf->setDistribution( KMFConfig::distribution() );
	conf->setIPTPath( KMFConfig::iPTPath() );
	conf->setInitPath( KMFConfig::initPath() );
	conf->setModprobePath( KMFConfig::modprobePath() );
	conf->setRcDefaultPath( KMFConfig::rcDefaultPath() );
	conf->setInterfaces( KMFConfig::interfaces() );
	KMFConfig::setConfigurationConverted( true );
	
	KMFConfig::writeConfig();
	
	const TQString & msg2 = i18n( "<qt><p><b>Configuration Imported!</b><br>" 
								"The current configuration was imported to <b>My Local Computer</b>.<br>"
								"Please check the imported configuration before you install the firewall</qt>" );
			KMessageBox::information( this, msg2, i18n( "Information" ) );
}

void KMFConfigDialog::slotReadConfig() {
	KMFConfig::self()->readConfig();
	
	m_cb_show_splash->setChecked( KMFConfig::showSplash() );
	m_cb_generic_interface->setChecked( KMFConfig::useGenericInterface() );
	
	m_cb_show_desc->setChecked( KMFConfig::showDocumentation() );
	m_cb_show_cmds->setChecked( KMFConfig::showCommandLine() );
	m_cb_show_objectID->setChecked( KMFConfig::showObjectID() );
	m_cb_useSSHForLocalhost->setChecked( KMFConfig::useSSHForLocalhost() );
	m_sb_max_undo->setValue( KMFConfig::maxUndo() );
}


void KMFConfigDialog::slotSaveConfig() {
	KMFConfig::setFirstRun( false );
	KMFConfig::setShowSplash(  m_cb_show_splash->isChecked() );
	
	KMFConfig::setUseGenericInterface( m_cb_generic_interface->isChecked() );
	
	KMFConfig::setShowDocumentation( m_cb_show_desc->isChecked() );
	KMFConfig::setShowCommandLine( m_cb_show_cmds->isChecked() );
	KMFConfig::setShowObjectID( m_cb_show_objectID->isChecked() );
	
	KMFConfig::setShowSelInterface( m_cb_show_selInterface->isChecked() );
	
	KMFConfig::setMaxUndo( m_sb_max_undo->value() );
	KMFConfig::setUseSSHForLocalhost( m_cb_useSSHForLocalhost->isChecked() );
	KMFConfig::self()->writeConfig();

	m_protocolPageEditProtocol->saveProtocols();
}

void KMFConfigDialog::setupGeneral() {
	TQFrame * page = addPage( i18n( "General Setting" ), TQString(), icon_general );
	TQGridLayout *lay = new TQGridLayout( page, 5, 2, 2 );
	m_cb_show_splash = new TQCheckBox( i18n( "Show splash screen on startup" ), page );
	m_cb_show_splash->setChecked( true );
	m_cb_show_selInterface = new TQCheckBox( i18n( "Show interface selection dialog at startup" ), page );
	m_cb_show_selInterface->setChecked( KMFConfig::showSelInterface() );
	
	TQGroupBox* gb_generic = new TQGroupBox( 2, Qt::Vertical, i18n("Generic Interface"), page, "gb_generic" );
	/*TQLabel *text1 = */new TQLabel( i18n( "<qt>By using the Generic Interface the creation of rulesets is much easier but it is not as flexible as the Normal Interface.</qt>" ), gb_generic );
	m_cb_generic_interface = new TQCheckBox( i18n( "Use the Generic Interface" ), gb_generic );
	m_cb_generic_interface->setChecked( KMFConfig::useGenericInterface() );
	connect( m_cb_generic_interface, TQT_SIGNAL( toggled( bool ) ), 
		this, TQT_SLOT( slotEnableGenericInterface( bool ) ) );

	TQLabel *text2 = new TQLabel( i18n( "<qt>Max. stored Undos:</qt>" ), page );
	m_sb_max_undo = new KIntSpinBox( 0, 100, 1, 10, 10, page, "spin_box" );
	m_sb_max_undo->setValue( 10 );
	m_b_enable_warnings = new KPushButton( i18n( "Reenable All Messages" ), page );
	m_b_enable_warnings->setFixedHeight( 30 );
	connect( m_b_enable_warnings, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotEnableWarnings() ) );
	
	TQLabel *text3 = new TQLabel( i18n( "<qt>By enabling KMyFirewall will communicate with the local computer using SSH. This will enable password keeping (e.g. KWallet support).</qt>" ), page );
	m_cb_useSSHForLocalhost = new TQCheckBox( i18n( "Use SSH for localhost communication" ), page );
	m_cb_useSSHForLocalhost->setChecked( KMFConfig::useSSHForLocalhost() );
	// connect( m_cb_useSSHForLocalhost, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotEnableLocalSSHUsage( bool ) ) );
	
	lay->addMultiCellWidget( gb_generic, 0, 0, 0, 1 );
	
	lay->addMultiCellWidget( m_cb_show_splash, 1, 1 , 0, 0 );
	lay->addMultiCellWidget( m_cb_show_selInterface, 1, 1, 1, 1 );
	
	lay->addMultiCellWidget( m_cb_useSSHForLocalhost, 2, 2, 0, 0, TQt::AlignTop );
	lay->addMultiCellWidget( text3, 2, 2, 1, 1, TQt::AlignTop );
	

	lay->addMultiCellWidget( text2, 3, 3 , 0, 0 );
	lay->addMultiCellWidget( m_sb_max_undo, 3, 3, 1, 1 );
	lay->addMultiCellWidget( m_b_enable_warnings, 4, 4, 0, 1 );
	
	TQSpacerItem* spacer = new TQSpacerItem( 0, 20, TQSizePolicy::Minimum, TQSizePolicy::Preferred );
	lay->addItem( spacer, 5, 0 );

}

void KMFConfigDialog::setupCustomProtocols(){
	TQFrame* editProtocolFrame = addPage(i18n("Custom Protocols"), i18n("Define your Custom Protocols here"), icon_edit_protocol_page );
	TQGridLayout *editProtocolLayout = new TQGridLayout( editProtocolFrame, 1, 1, 2, 2 );
	m_protocolPageEditProtocol = new KMFGenericInterfaceEditProtocol( editProtocolFrame ,"m_protocolPageEditProtocol");
	editProtocolLayout->addWidget( m_protocolPageEditProtocol,0,0 );
}

void KMFConfigDialog::registerCompiler( KMFCompilerInterface* compiler ) {
	kdDebug() << "KMFConfigDialog::registerCompiler: OS: " << compiler->osGUIName() << " Backend: " << compiler->backendGUIName() << endl;
	// m_cb_os->insertItem( compiler->osGUIName() );
	TQStringList *stl = new TQStringList();
	stl->append( compiler->osName() );
	stl->append( compiler->osGUIName() );
	stl->append( compiler->backendName() );
	stl->append( compiler->backendGUIName() );
	m_backends->append( stl );
}

void KMFConfigDialog::setupListView() {
	TQFrame * page = addPage( i18n( "Listview Preferences" ), TQString(), icon_listview );
	TQGridLayout *lay = new TQGridLayout( page, 5, 1, 2 );
	m_lvp_text1 = new TQLabel( i18n( "<qt>Define here if you like to see the documentation  "
	                                 "for tables and built-in chains in the main listview.</qt>" ), page );
	lay->addWidget( m_lvp_text1, 0, 0 );
	m_cb_show_desc = new TQCheckBox( i18n( "Show documentation for all Objects." ), page );
	lay->addWidget( m_cb_show_desc, 1, 0 );

	m_lvp_text2 = new TQLabel( i18n( "<qt>Turn this box on of you like to see the "
	                                  "generated iptables command lines in the main listview</qt>" ), page );
	lay->addWidget( m_lvp_text2, 2, 0 );

	m_cb_show_cmds = new TQCheckBox( i18n( "Show iptables commands." ), page );
	lay->addWidget( m_cb_show_cmds, 3, 0 );

	
	m_lvp_text3 = new TQLabel( i18n( "<qt>Enable this to show the internally-used Object IDs in the listview. Mainly useful for debuging.</qt>" ), page );
	lay->addWidget( m_lvp_text3, 4, 0 );
	
	
	m_cb_show_objectID = new TQCheckBox( i18n( "Show objectIDs." ), page );
	lay->addWidget( m_cb_show_objectID, 5, 0 );
	
	
	TQLabel *m_lvp_text4 = new TQLabel( i18n( "<qt><b>Note:</b> Those settings are only available for the normal interface. This options are disabled when using the generic interface.</qt>" ), page );
	lay->addWidget( m_lvp_text4, 6, 0 );
	TQSpacerItem* spacer = new TQSpacerItem( 0, 20, TQSizePolicy::Minimum, TQSizePolicy::Preferred );
	lay->addItem( spacer, 7, 0 );
}

void KMFConfigDialog::setupPlugins(){
	kdDebug() << "\nvoid KMFConfigDialog::setupPlugins()" << endl;
	TQFrame * page = addPage( i18n( "Plugins" ), TQString(), icon_listview );
	TQVBoxLayout *lay = new TQVBoxLayout( page );
	TQLabel *text1 = new TQLabel( i18n( "<qt>In the list you can see which plugins have been found.</qt>" ), page );
	lay->addWidget( text1 );
	m_lv_plugins = new KListView( page );
	m_lv_plugins->addColumn( i18n("Name") );
	m_lv_plugins->addColumn( i18n("Description") );
	m_lv_plugins->addColumn( i18n("Library") );
	lay->addWidget( m_lv_plugins );
}

void KMFConfigDialog::checkPlugins() {
	kdDebug() << "void KMFConfigDialog::checkPlugins()" << endl;
	m_lv_plugins->clear();
	KListViewItem *item_installers = new KListViewItem( m_lv_plugins, 0,0 );
	item_installers->setText( 0, i18n("Installers") );
	item_installers->setOpen( true );
	
	KListViewItem *item_compilers = new KListViewItem( m_lv_plugins, 0,0 );
	item_compilers->setText( 0, i18n("Compilers") );
	item_compilers->setOpen( true );
	
	KListViewItem *item_optioneditors = new KListViewItem( m_lv_plugins, 0,0 );
	item_optioneditors->setText( 0, i18n("Rule Option Editors") );
	item_optioneditors->setOpen( true );
	
	KListViewItem *item_targetoptioneditors = new KListViewItem( m_lv_plugins, 0,0 );
	item_targetoptioneditors->setText( 0, i18n("Rule Target Option Editors") );
	item_targetoptioneditors->setOpen( true );
	
	// kdDebug() << "Start query" << endl;
	KTrader::OfferList offers = KTrader::self()->query( "KMyFirewall/Installer");
	// kdDebug() << "Query performed for KMyFirewall/Installer" << endl;
	KTrader::OfferList::iterator it;
	if ( offers.empty() ) {
		KListViewItem *item = new KListViewItem( item_installers, 0,0);
		item->setText(0, i18n("No installer plugins found!") );
		kdDebug() << "NO MATCHING PLUGIN FOUND" << endl;
	}
	for ( it = offers.begin(); it != offers.end(); ++it ) {
		KService::Ptr ptr = *it;
		KListViewItem *item = new KListViewItem( item_installers, 0,0);
		item->setText(0, ptr->name() );
		item->setText(1, ptr->comment() );
		item->setText(2, ptr->library().local8Bit().data() );
	}
	
	KTrader::OfferList offers2 = KTrader::self()->query( "KMyFirewall/Compiler" );
	// kdDebug() << "Query performed for KMyFirewall/Compiler" << endl;
	if ( offers2.empty() ) {
		KListViewItem *item = new KListViewItem( item_compilers, 0,0);
		item->setText(0, i18n("No compiler plugins found!") );
		kdDebug() << "NO MATCHING PLUGIN FOUND" << endl;
	}
	for ( it = offers2.begin(); it != offers2.end(); ++it ) {
		KService::Ptr ptr = *it;
		KListViewItem *item = new KListViewItem( item_compilers, 0,0);
		item->setText(0, ptr->name() );
		item->setText(1, ptr->comment() );
		item->setText(2, ptr->library().local8Bit().data() );
		// kdDebug() << "Found Plugin: " << ptr->name()  << "\nLibrary: "<<  ptr->library().local8Bit().data()  <<endl;
		KLibFactory *factory = KLibLoader::self()->factory( ptr->library().local8Bit().data() );
		kdDebug() << KLibLoader::self()->lastErrorMessage() << endl;

		if ( !factory ) {
			KMessageBox::error( 0, i18n("<qt><b>Compiler plugin could not be loaded.</b></qt>") );
			kdDebug() << "Couldn't load plugin: "  <<  ptr->name() << endl;
		}
		
		if ( KMFCompilerInterface *part = dynamic_cast<KMFCompilerInterface*> ( factory->create( TQT_TQOBJECT(this) , "KMFCompilerInterface") ) ) {
			// kdDebug() << "Returning Compiler Plugin." << endl;
			registerCompiler( part );
		}
	}
	
	
	
	KTrader::OfferList offers3 = KTrader::self()->query( "KMyFirewall/RuleOptionEdit" );
	// kdDebug() << "Query performed for KMyFirewall/RuleOptionEdit" << endl;
	if ( offers3.empty() ) {
		KListViewItem *item = new KListViewItem( item_optioneditors, 0,0);
		item->setText(0, i18n("No RuleOptionEdit plugins found.") );
		kdDebug() << "NO MATCHING PLUGIN FOUND" << endl;
	}
	
	for ( it = offers3.begin(); it != offers3.end(); ++it ) {
		KService::Ptr ptr = *it;
		KListViewItem *item = new KListViewItem( item_optioneditors, 0,0);
		item->setText(0, ptr->name() );
		item->setText(1, ptr->comment() );
		item->setText(2, ptr->library().local8Bit().data() );
		// kdDebug() << "Found Plugin: " << ptr->name()  << "\nLibrary: "<<  ptr->library().local8Bit().data()  <<endl;
	}

	KTrader::OfferList offers4 = KTrader::self()->query( "KMyFirewall/RuleTargetOptionEdit" );
	// kdDebug() << "Query performed for KMyFirewall/RuleTargetOptionEdit" << endl;
	if ( offers4.empty() ) {
		KListViewItem *item = new KListViewItem( item_targetoptioneditors, 0,0);
		item->setText(0, i18n("No RuleTargetOptionEdit plugins found.") );
		kdDebug() << "NO MATCHING PLUGIN FOUND" << endl;
	}
	for ( it = offers4.begin(); it != offers4.end(); ++it ) {
		KService::Ptr ptr = *it;
		KListViewItem *item = new KListViewItem( item_targetoptioneditors, 0,0);
		item->setText(0, ptr->name() );
		item->setText(1, ptr->comment() );
		item->setText(2, ptr->library().local8Bit().data() );
		// kdDebug() << "Found Plugin: " << ptr->name()  << "\nLibrary: "<<  ptr->library().local8Bit().data()  <<endl;
	}
}

void KMFConfigDialog::slotEnableGenericInterface( bool enable ) {
	if ( enable != KMFConfig::useGenericInterface() )
		KMessageBox::information( this, i18n( "<qt>Please not that you have to restart KMyFirewall to make the changes take effect. </qt>" ), TQString( "" ), "info_change_interface" );
}

// void KMFConfigDialog::slotEnableLocalSSHUsage( bool enable ) {
// 	KMFConfig::setUseSSHForLocalhost( enable );	
// }


void KMFConfigDialog::slotEnableWarnings() {
	kdDebug() << "KMFConfigDialog::slotEnableWarnings()" << endl;
	KMessageBox::enableAllMessages();
	KMessageBox::information( this, i18n( "Reenabled all warnings." ) );
}

void KMFConfigDialog::loadIcons() {
	KIconLoader * loader = KGlobal:: iconLoader();
	TQString icon_name;

	icon_name = "about_kde";
	icon_general = loader->loadIcon( icon_name, KIcon::Desktop );

	icon_name = "folder";
	icon_paths = loader->loadIcon( icon_name, KIcon::Desktop );

	icon_name = "network";
	icon_interfaces = loader->loadIcon( icon_name, KIcon::Desktop );

	icon_name = "view_tree";
	icon_listview = loader->loadIcon( icon_name, KIcon::Desktop );
	
	icon_name = "nfs_unmount";
	icon_edit_protocol_page = loader->loadIcon( icon_name, KIcon::Desktop );
}

}

