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


#include "kmftransactionlog.h"

// QT includes
#include <tqstring.h>
#include <tqvaluelist.h>
#include <tqlistview.h>
#include <tqptrlist.h>
#include <tqtimer.h>
#include <tqtextedit.h>
#include <tqtextstream.h>
#include <tqtextbrowser.h>

// KDE includes
#include <klistview.h>
#include <klocale.h>
#include <kdebug.h>
#include <kpushbutton.h>
#include <kpopupmenu.h>
#include <kprocess.h>
#include <ktempfile.h>

// project includes
#include "../core/netfilterobject.h"
#include "../core/kmfundoengine.h"
#include "../core/kmftransaction.h"
namespace KMF {
KMFTransactionLog* KMFTransactionLog::s_instance = 0;
KMFTransactionLog* KMFTransactionLog::instance() {
	if ( ! s_instance ) {
		s_instance = new KMFTransactionLog( 0, "", 0 );
		
	}
	
	return s_instance;
}

KMFTransactionLog::KMFTransactionLog ( TQWidget* parent, const char* name, WFlags fl ) : KMyFirewallTransactionLog ( parent,name,fl ) {
	m_contextMenu = new KPopupMenu( this, "m_contextMenu" );
	m_currentTransaction = 0;
	m_undoXMLFile = new KTempFile();
	m_undoXMLFile->setAutoDelete( true );
	m_redoXMLFile = new KTempFile();
	m_redoXMLFile->setAutoDelete( true );
	
	connect( m_cmd_clearStacks, TQT_SIGNAL( clicked() ),
		this, TQT_SLOT( slotClearStacks() ) );	
	connect( m_cmd_clearLog, TQT_SIGNAL( clicked() ),
		this, TQT_SLOT( slotClearLog() ) );	
		
	connect( KMFUndoEngine::instance(), TQT_SIGNAL( sigStackChanged() ),
		this, TQT_SLOT( slotUpdateView() ) );
		
	connect( KMFUndoEngine::instance(), TQT_SIGNAL( sigLog( const TQString& ) ),
		this, TQT_SLOT( slotLog( const TQString& ) ) );
	
	connect( m_lvUndoTransactions, TQT_SIGNAL( contextMenuRequested ( TQListViewItem*, const TQPoint&, int ) ),
		this, TQT_SLOT( slotZoneRBM( TQListViewItem*, const TQPoint&, int ) ) );
	
	connect( m_lvRedoTransactions, TQT_SIGNAL( contextMenuRequested ( TQListViewItem*, const TQPoint&, int ) ),
		this, TQT_SLOT( slotZoneRBM( TQListViewItem*, const TQPoint&, int ) ) );
	
	connect( m_cmd_update, TQT_SIGNAL( clicked() ),
		this, TQT_SLOT( slotUpdateStatistics() ) );
	
	m_lvUndoTransactions->setSorting(-1);
   	m_lvUndoTransactions->setSortColumn(-1);
	
	m_lvRedoTransactions->setSorting(-1);
   	m_lvRedoTransactions->setSortColumn(-1);
}

KMFTransactionLog::~KMFTransactionLog() {}

void KMFTransactionLog::slotUpdateStatistics() {
	kdDebug() << "KMFTransactionLog::slotUpdateStatistics()" << endl;
	m_txt_stats->setText( "" );
			
	m_txt_stats->append ( "Object count:      " + TQString::number( NetfilterObject::objectCount( -1 ) ) );
	m_txt_stats->append ( "\n" );
		
	m_txt_stats->append ( "KMFNETWORKs:       " + TQString::number( NetfilterObject::objectCount( NetfilterObject::KMFNETWORK ) ) );	

	m_txt_stats->append ( "IPTABLES_RULESETs: " + TQString::number( NetfilterObject::objectCount( NetfilterObject::IPTABLES_RULESET ) ) );
	m_txt_stats->append ( "GENERIC_RULESETs:  " + TQString::number( NetfilterObject::objectCount( NetfilterObject::GENERIC_RULESET ) ) );	

	m_txt_stats->append ( "TABLEs:            " + TQString::number( NetfilterObject::objectCount( NetfilterObject::TABLE ) ) );
	m_txt_stats->append ( "CHAINs:            " + TQString::number( NetfilterObject::objectCount( NetfilterObject::CHAIN ) ) );
	m_txt_stats->append ( "RULEs:             " + TQString::number( NetfilterObject::objectCount( NetfilterObject::RULE ) ) );
	m_txt_stats->append ( "RULEOPTIONs:       " + TQString::number( NetfilterObject::objectCount( NetfilterObject::RULEOPTION ) ) );
	m_txt_stats->append ( "PROTOCOLs:         " + TQString::number( NetfilterObject::objectCount( NetfilterObject::PROTOCOL ) ) );
	m_txt_stats->append ( "NETZONEs:          " + TQString::number( NetfilterObject::objectCount( NetfilterObject::NETZONE ) ) );
	m_txt_stats->append ( "NETHOSTs:          " +TQString::number( NetfilterObject::objectCount( NetfilterObject::NETHOST ) ) );
	m_txt_stats->append ( "KMFTARGETs:        " + TQString::number( NetfilterObject::objectCount( NetfilterObject::KMFTARGET ) ) );
	m_txt_stats->append ( "KMFTARGETCONFIGs:  " + TQString::number( NetfilterObject::objectCount( NetfilterObject::KMFTARGETCONFIG ) ) );
	m_txt_stats->append ( "PROTOCOLUSAGEs:    " + TQString::number( NetfilterObject::objectCount( NetfilterObject::PROTOCOLUSAGE ) ) );
	
	
	m_txt_stats->append ( "PROTOCOLCATEGORYs: " + TQString::number( NetfilterObject::objectCount( NetfilterObject::PROTOCOLCATEGORY ) ) );
}

void KMFTransactionLog::slotZoneRBM( TQListViewItem* item, const TQPoint& point, int ) {
	if ( ! item ) {
		kdDebug() << "No item Setelcted" << endl;
		m_currentTransaction = 0;
		return;
	}
	
	
	TQUuid uid( item->text( 1 ) );
	KMFTransaction *t = KMFUndoEngine::instance()->findTransction( uid );
	if ( ! t ) {
		m_currentTransaction = 0;
		return;
	}
	
	m_currentTransaction = t;
	m_contextMenu->clear();
	TQString name = i18n("Transaction: %1").arg( m_currentTransaction->uuid().toString() );
	// TQString lab_str = i18n("Zone: %1").arg( m_zone->guiName() );
	m_contextMenu->insertTitle( name );
	m_contextMenu->insertItem( i18n( "Show XML diff using Kompare" ), this, TQT_SLOT( slotShowDiff() ) );
	m_contextMenu->popup( point );
	
	if ( m_undoXMLFile ) {
		m_undoXMLFile->unlink();
		delete m_undoXMLFile;
		m_undoXMLFile = 0;
	} 
	if ( m_redoXMLFile ) {
		m_redoXMLFile->unlink();
		delete m_redoXMLFile;
		m_redoXMLFile = 0;
	} 
	m_undoXMLFile = new KTempFile();
	m_undoXMLFile->setAutoDelete( true );
	m_redoXMLFile = new KTempFile();
	m_redoXMLFile->setAutoDelete( true );
	
	TQTextStream& sUndo = *m_undoXMLFile->textStream();
	sUndo << m_currentTransaction->undoXML();
	m_undoXMLFile->sync();
	
	TQTextStream& sRedo = *m_redoXMLFile->textStream();
	sRedo << m_currentTransaction->redoXML();
	m_redoXMLFile->sync();
}

void KMFTransactionLog::slotShowDiff() {
	kdDebug() << "KMFTransactionLog::slotShowDiff()" << endl;
	if ( ! m_currentTransaction ) {
		return;
	}
	
	 KProcess* childproc = new KProcess();
	 kdDebug() << "kompare " << m_undoXMLFile->name() << m_redoXMLFile->name() << endl;
	 *childproc << "kompare" << m_undoXMLFile->name() << m_redoXMLFile->name();
	 childproc->start( KProcess::NotifyOnExit, KProcess::NoCommunication );
}

void KMFTransactionLog::slotKompareExited( KProcess* ) {
}

void KMFTransactionLog::slotClearStacks() {
	KMFUndoEngine::instance()->clearStacks();	
	slotUpdateView();
}

void KMFTransactionLog::slotClearLog() {
	m_txt_transactionLog->clear();
}
void KMFTransactionLog::slotLog( const TQString& msg ) {
	m_txt_transactionLog->append( msg );
}

void KMFTransactionLog::slotUpdateView() {
//	kdDebug() << "KMFTransactionLog::updateView()" << endl;
	KListViewItem* last = 0;
	TQValueList< KMFTransaction* > undos = KMFUndoEngine::instance()->undoTransactions();
	TQValueList< KMFTransaction* >::iterator itUndo;
	for ( itUndo = undos.begin(); itUndo != undos.end(); ++itUndo ) {
		KMFTransaction* trans = *itUndo;
		last = setupListItem( trans, m_lvUndoTransactions, last );
	}
	
	TQPtrList<TQListViewItem>* del = new TQPtrList<TQListViewItem>;
	del->setAutoDelete( true );
	TQListViewItem* item = m_lvUndoTransactions->firstChild();
	while( item ) {
		bool found = false;
		for ( itUndo = undos.begin(); itUndo != undos.end(); ++itUndo ) {
			KMFTransaction* trans = *itUndo;
			if ( trans->uuid().toString() == item->text( 1 ) ) {
				found = true;
			}
		}	
		if ( ! found ) {
			del->append( item );
		}
		item = item->nextSibling();
	}
	del->clear();
	
	last = 0;
	TQValueList< KMFTransaction* > redos = KMFUndoEngine::instance()->redoTransactions();
	TQValueList< KMFTransaction* >::iterator itRedo;
	for ( itRedo = redos.begin(); itRedo != redos.end(); ++itRedo ) {
		KMFTransaction* trans = *itRedo;
		last = setupListItem( trans, m_lvRedoTransactions,last );
	}
	
	item = m_lvRedoTransactions->firstChild();
	while( item ) {
		bool found = false;
		for ( itRedo = redos.begin(); itRedo != redos.end(); ++itRedo ) {
			KMFTransaction* trans = *itRedo;
			if ( trans->uuid().toString() == item->text( 1 ) ) {
				found = true;
			}
		}	
		if ( ! found ) {
			del->append( item );
		}
		item = item->nextSibling();
	}
	del->clear();
}

KListViewItem* KMFTransactionLog::setupListItem( KMFTransaction* trans, KListView* list, KListViewItem* after ) {
	// kdDebug() << "Search transaction: " << trans->uuid().toString() << endl;
 	TQListViewItem* found = 0;
	
	found = list->findItem ( trans->uuid().toString(), 1 );
	if ( found ) {
		return (KListViewItem*) found;
	}
	// kdDebug() << "No Item Found" << endl;


	KListViewItem* item = new KListViewItem( list, after );
	item->setText( 0, trans->name() );
	item->setText( 1, trans->uuid().toString() );

	KListViewItem* last = 0;
/*	TQValueList<int>& objectIds = trans->objectIDs();
	TQValueList<int>::iterator it;
	
	for ( it = objectIds.begin(); it != objectIds.end(); ++it ) {*/
		TQString obj_uuid = trans->objectUuid().toString();
		KListViewItem* itemID = new KListViewItem( item, last, "", obj_uuid );
		last = itemID;
		NetfilterObject *obj = 0;
		obj = NetfilterObject::findObject ( obj_uuid );
		if ( obj ) {
			itemID->setText( 0, i18n("Object: %1").arg( obj->name() ) );
			// itemID->setText( 2, obj->name() );
			// itemID->setText( 3, obj->getXMLSniplet() );
		}
// 	}
	return item;
}

}

#include "kmftransactionlog.moc"

