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

// QT includes
#include <tqptrlist.h>
#include <tqmultilineedit.h>
#include <tqtabwidget.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/xmlnames.h"
#include "../../core/kmfrulesetdoc.h"
#include "../../core/kmfgenericdoc.h"
#include "../../core/kmfiptdoc.h"
#include "../../core/kmferror.h"
#include "../../core/kmferrorhandler.h"
#include "../../core/kmfconfig.h"
#include "../../core/kmftarget.h"
#include "../../kmfwidgets/kmflistview.h"
#include "../../kmfwidgets/kmfselectactivetarget.h"

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

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

	m_errorHandler = new KMFErrorHandler( "KMFIPTablesCompiler" );
	m_iptWidget = 0;
	new KAction( i18n( "&Export as IPTables (Linux) Script" ),  "fileexport",
	                             0, this, TQT_SLOT( slotExportIPT() ), actionCollection(), "compile_iptables" );
	
	if ( genericDoc() ) {
		new KAction( i18n( "&Convert to IPTables Document and View" ),  "fileexport",
		                                   0, this, TQT_SLOT( slotConvertToIPTDoc() ), actionCollection(), "convert_to_iptdoc" );

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


KMFIPTablesCompiler::~KMFIPTablesCompiler() {}

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

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

void KMFIPTablesCompiler::slotExportIPT() {
	kdDebug() << "KMFIPTablesCompiler::slotExportIPT()" << endl;
	
	KMFTarget* tg = KMFSelectActiveTarget::selectTarget( network(), i18n("<qt><p>Please select target from which the configuration should be exported as iptables script.</p></qt>") );
		
	if ( ! tg ) {
		return;
	}
	
	
	
	
	KURL url = KFileDialog::getSaveURL( ":", "*.sh|Shell Script (*.sh)" );
	TQString filename = url.fileName();
	if ( url.fileName().isEmpty() )
		return ;
	int answer = 0;
	while ( answer != 3 ) {
		if ( KIO::NetAccess::exists( url, false, KApplication::kApplication()->mainWidget() ) ) {
			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;
		}
	}
	TQString extension = filename.right( 3 );
	if ( extension != ".sh" )
		filename.append( ".sh" );
	url.setFileName( filename );
	KTempFile tempfile;
	
	
	m_err = tg->rulesetDoc()->createFirewallScript( tempfile.name() );
	
	
		
	if ( m_errorHandler->showError( m_err ) ) {
		if ( KIO::NetAccess::upload( tempfile.name(), url, KApplication::kApplication()->mainWidget() ) ) {
		//	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() {
// 	//	TQString s = compile( genericDoc() );
// 	TQMultiLineEdit* ed = new TQMultiLineEdit( 0, "edit" );
// 	if ( genericDoc() ) {
// 		ed->setText( compile( genericDoc() ) );
// 	} else if ( iptablesDoc() ) {
// 		ed->setText( compile( iptablesDoc() ) );
// 	}
// 	setOutputWidget( ed );
// 	showOutput();
// }

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

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

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

	if ( ! m_iptWidget ) {
		m_iptWidget = new TQTabWidget( 0 , TQTABWIDGET_OBJECT_NAME_STRING );
		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( m_iptdoc->table( Constants::FilterTable_Name ) );
	m_iptViewFilter->slotUpdateView();
	
	m_iptViewNat ->setEnabled( true );
	m_iptViewNat->clear();
	m_iptViewNat->slotLoadNode( m_iptdoc->table( Constants::NatTable_Name ) );
	m_iptViewNat->slotUpdateView();
	
	m_iptViewMangle ->setEnabled( true );
	m_iptViewMangle->clear();
	m_iptViewMangle->slotLoadNode( m_iptdoc->table( Constants::MangleTable_Name ) );
	m_iptViewMangle->slotUpdateView();

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

// 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( TQObject* parent, const char* name )
		: KLibFactory( parent, name ) {
	// 	s_instance = new KInstance( "KMFIPTablesCompilerFactory" );
}

TQObject* KMFIPTablesCompilerFactory::createObject( TQObject* parent, const char* name,
        const char*, const TQStringList & ) {
	TQObject * 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"
