//
// C++ Implementation: kmfiptablescompiler
//
// Description:
//
//
// Author: Christian Hubinger <chubinger@gmail.com>, (C) 2003
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "kmfiptablescompiler.h"

// QT includes
#include <qptrlist.h>
#include <qmultilineedit.h>
#include <qtabwidget.h>

// KDE includes
#include <kdebug.h>
#include <klocale.h>
#include <kstandarddirs.h>
#include <kfiledialog.h>
#include <ktempfile.h>
#include <kio/netaccess.h>
#include <kmessagebox.h>
#include <kapplication.h>

// Project includes
#include "../../version.h"
#include "../../core/kmfgenericdoc.h"
#include "../../core/kmfiptdoc.h"
#include "../../core/kmferror.h"
#include "../../core/kmferrorhandler.h"
#include "../../core/kmfconfig.h"
#include "../../kmfwidgets/kmflistview.h"

#include "kmfiptablesscriptgenerator.h"
#include "kmfiptablesdocumentconverter.h"

KMFIPTablesCompiler::KMFIPTablesCompiler( QObject* parent, const char* name ) : KMFPlugin( parent, name )  {
	m_osName = i18n("linux");
	m_osGUIName = i18n("Linux");
	m_backendName = i18n("iptables");
	m_backendGUIName = i18n("IPTables");

	m_errorHandler = new KMFErrorHandler( "KMFIPTablesCompiler" );
	m_iptWidget = 0;
	new KAction( i18n( "&Export as IPTables (Linux) Script" ),  "fileexport",
	                             0, this, SLOT( slotExportIPT() ), actionCollection(), "compile_iptables" );

	new KAction( i18n( "&Show IPTables (Linux) Script" ),  "fileexport",
	                                 0, this, SLOT( slotShowIPTScript() ), actionCollection(), "show_iptables_sript" );
	if ( genericDoc() ) {
		new KAction( i18n( "&Convert to IPTables Document and View" ),  "fileexport",
		                                   0, this, SLOT( slotConvertToIPTDoc() ), actionCollection(), "convert_to_iptdoc" );

		setXMLFile( "kmfiptablescompiler.rc" );
		kdDebug() << "KMFIPTablesCompiler: Finished initialisation." << endl;
	}
}


KMFIPTablesCompiler::~KMFIPTablesCompiler() {}

const QString& KMFIPTablesCompiler::osName(){
	return m_osName;
}
const QString& KMFIPTablesCompiler::osGUIName(){
	return m_osGUIName;
}
const QString& KMFIPTablesCompiler::backendName(){
	return m_backendName;
}
const QString& KMFIPTablesCompiler::backendGUIName(){
	return m_backendGUIName;
}

void KMFIPTablesCompiler::compile() {
	kdDebug() << "void KMFIPTablesCompiler::compile()" << endl;
}

void KMFIPTablesCompiler::slotExportIPT() {
	kdDebug() << "KMFIPTablesCompiler::slotExportIPT()" << endl;
	KURL url = KFileDialog::getSaveURL( ":", "*.sh|Shell Script (*.sh)" );
	QString filename = url.fileName();
	if ( url.fileName().isEmpty() )
		return ;
	int answer = 0;
	while ( answer != 3 ) {
		if ( KIO::NetAccess::exists( url, false,0 ) ) {
			if ( answer == 4 ) {
				slotExportIPT();
				return ;
			} else {
				answer = KMessageBox::warningYesNo( 0, i18n( "<qt>File <b>%1</b> already exists!</p>"
				                                    "<p><b>Overwrite the existing file?</b></p></qt>" ).arg( url.url() ) );
			}
		} else {
			answer = 3;
		}
	}
	QString extension = filename.right( 3 );
	if ( extension != ".sh" )
		filename.append( ".sh" );
	//	kdDebug() << "Found File name extention: " << extention << endl;
	url.setFileName( filename );
	KTempFile tempfile;
	
	
	if ( genericDoc() ) {
		KMessageBox::error( 0, "WARNING: KMFIPTablesCompiler::slotExportIPT() Export for generic document class not implemented" );
		return;
	} else if ( iptablesDoc() ) {
		m_err = iptablesDoc()->createFirewallScript( tempfile.name() );
	} else {
		kdDebug() << "ERROR: KMFIPTablesCompiler::slotExportIPT() No document class found" << endl;
	}
		
		
		
	if ( m_errorHandler->showError( m_err ) ) {
		if ( KIO::NetAccess::upload( tempfile.name(), url, 0 ) ) {
		//	statusBar() ->message( i18n( "Wrote file: " ) + url.fileName() , 5000 );
		} else {
			kdDebug() << "Couldn't upload file!!!" << tempfile.name() << endl;
			KMessageBox::detailedError( 0, i18n( "<qt><p>Saving file: <b>%1</b> Failed.</p></qt>" ).arg( url.url() ),
										i18n( "<qt><p>If you are working with remotely stored files "
												"make sure that the target host and the directory is reachable. "
												"</p></qt>" ) );
		}
	}
	
	tempfile.unlink();
}

void KMFIPTablesCompiler::slotShowIPTScript() {
	//	QString s = compile( genericDoc() );
	QMultiLineEdit* ed = new QMultiLineEdit( 0, "edit" );
	if ( genericDoc() ) {
		ed->setText( compile( genericDoc() ) );
	} else if ( iptablesDoc() ) {
		ed->setText( compile( iptablesDoc() ) );
	}
	setOutputWidget( ed );
	showOutput();
}

const QString& KMFIPTablesCompiler::compile( KMFGenericDoc* doc ) {
	kdDebug() << "const QString& KMFIPTablesCompiler::compile( KMFGenericDoc* doc )" << endl;
	//kdDebug() << "Doc XLM:\n" << m_genericDoc->getXMLSniplet() << endl;
	KMFIPTablesDocumentConverter *converter = new KMFIPTablesDocumentConverter();
	KMFIPTDoc *iptdoc = converter->compileToIPTDoc( doc );
	delete converter;
	
	if ( iptdoc )
		return *( new QString( iptdoc->compile() ) );
	else
		return *( new QString( "ERROR: Couldn't compile document - may be wrong type " ) );
}

const QString& KMFIPTablesCompiler::compile( KMFIPTDoc* doc ) {
	KMFIPTablesScriptGenerator *generator = new  KMFIPTablesScriptGenerator();
	QString script = generator->compile( doc );
	delete generator;
	return *(new QString( script ) );
}

void KMFIPTablesCompiler::slotConvertToIPTDoc() {
	if ( ! doc() ) {
		kdDebug() << "No document Available to compile" << endl;
		return;
	}
	KMFIPTablesDocumentConverter *converter = new KMFIPTablesDocumentConverter();
	KMFIPTDoc *iptdoc = converter->compileToIPTDoc( genericDoc() );
	delete converter;

	if ( ! m_iptWidget ) {
		m_iptWidget = new QTabWidget( 0 , "QTabWidget" );
		m_iptViewFilter = new KMFListView( 0, "view" );
		m_iptViewNat = new KMFListView( 0, "view" );
		m_iptViewMangle = new KMFListView( 0, "view" );
		m_iptWidget ->addTab( m_iptViewFilter, "Filter" );
		m_iptWidget ->addTab( m_iptViewNat, "Nat" );
		m_iptWidget ->addTab( m_iptViewMangle, "Mangle" );
	}
	m_iptViewFilter ->setEnabled( true );
	m_iptViewFilter->clear();
	m_iptViewFilter->slotLoadNode( iptdoc->table( "filter" ) );
	m_iptViewFilter->slotUpdateView();
	
	m_iptViewNat ->setEnabled( true );
	m_iptViewNat->clear();
	m_iptViewNat->slotLoadNode( iptdoc->table( "nat" ) );
	m_iptViewNat->slotUpdateView();
	
	m_iptViewMangle ->setEnabled( true );
	m_iptViewMangle->clear();
	m_iptViewMangle->slotLoadNode( iptdoc->table( "mangle" ) );
	m_iptViewMangle->slotUpdateView();

	m_iptWidget->setMinimumSize( 800, 600 );
	m_iptWidget->show();
	m_iptWidget->raise();
}

// It's usually safe to leave the factory code alone.. with the
// notable exception of the KAboutData data
#include <kaboutdata.h>
#include <klocale.h>

// KInstance* KMFIPTablesCompilerFactory::s_instance = 0L;
// KAboutData* KMFIPTablesCompilerFactory::s_about = 0L;

KMFIPTablesCompilerFactory::KMFIPTablesCompilerFactory( QObject* parent, const char* name )
		: KLibFactory( parent, name ) {
	// 	s_instance = new KInstance( "KMFIPTablesCompilerFactory" );
}

QObject* KMFIPTablesCompilerFactory::createObject( QObject* parent, const char* name,
        const char*, const QStringList & ) {
	QObject * obj = new KMFIPTablesCompiler( parent, name );
	emit objectCreated( obj );
	return obj;
}


// KInstance* KMFIPTablesCompilerFactory::instance() {
// 	if ( !s_instance ) {
// 		s_instance = new KInstance( "KMFIPTablesCompilerFactory" );
// 	}
// 	return s_instance;
// }

extern "C" {
	void* init_libkmfcompiler_ipt() {
		return new KMFIPTablesCompilerFactory;
	}
}

#include "kmfiptablescompiler.moc"
