/***************************************************************************
 *                                                                         *
 *   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@gmail.com>, (C) 2001-2004
*/



#include "kmflistview.h"

// QT includes
#include <qstring.h>
#include <qptrlist.h>
#include <kiconloader.h>

// KDE includes
#include <kapplication.h>
#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kconfig.h>

// Project includes
#include "../core/netfilterobject.h"
#include "../core/kmfdoc.h"
#include "../core/iptable.h"
#include "../core/iptchain.h"
#include "../core/iptrule.h"
#include "../core/iptruleoption.h"
#include "../core/kmfconfig.h"
#include "../core/kmfappstate.h"
#include "../kmyfirewall.h"
#include "kmflistviewitem.h"

KMFListView::KMFListView( QWidget *parent, const char *name ) : KListView( parent, name ) {
	loadIcons();
	connect( this, SIGNAL( sigLoadNode( NetfilterObject* ) ),
	         this, SLOT( slotLoadNode( NetfilterObject* ) ) );
	cast_error = i18n( "ERROR: Wrong ListViewItem Class used!\nThis is no KMFListViewItem" );
	setSorting(0,true);
	m_show_desc = true;
	m_show_cmds = false;
	m_show_objectID = false;
	m_NetfilterObject = 0;


	addColumn( i18n( "Rule No." ) );
	addColumn( QString::null );
	addColumn( i18n( "Value" ) );
	setSizePolicy( QSizePolicy( ( QSizePolicy::SizeType ) 2, ( QSizePolicy::SizeType ) 2, 0, 0,
	                                  sizePolicy().hasHeightForWidth() ) );
	setFrameShape( KListView::StyledPanel );
	setFrameShadow( KListView::Sunken );
	setSorting( 0, true );
	setFullWidth( true );
	setItemsMovable( true );
	setDropHighlighter( true );
	setDropVisualizer( true );
	setSelectionMode( QListView::Single );

}


KMFListView::~KMFListView() {}

void KMFListView::slotLoadNode( NetfilterObject* node ) {
	kdDebug() << "void KMFListView::loadNode( NetfilterObject* node )" << endl;
	if ( ! node )
		return;
	m_NetfilterObject = node;



	if ( m_NetfilterObject->type() == NetfilterObject::TABLE ) {
		if ( IPTable * table = dynamic_cast<IPTable*> ( node ) ) {
			bool changed = false;
			if ( KMFConfig::showDocumentation() ) {
				if ( ! m_show_desc )
					changed = true;
				m_show_desc = true;
			} else {
				if ( m_show_desc )
					changed = true;
				m_show_desc = false;
			}
			if (  KMFConfig::showCommandLine() ) {
				if ( ! m_show_cmds )
					changed = true;
				m_show_cmds = true;
			} else {
				if ( m_show_cmds )
					changed = true;
				m_show_cmds = false;
			}
			if (  KMFConfig::showObjectID() ) {
				if ( ! m_show_objectID )
					changed = true;
				m_show_objectID = true;
			} else {
				if ( m_show_objectID )
					changed = true;
				m_show_objectID = false;
			}
			setUpdatesEnabled( false );
			setupTableView( table );
			setUpdatesEnabled( true );
			sort();
			triggerUpdate();
		} else {
			KMessageBox::error( this, i18n( "Found invalid ListViewItem." ), i18n( "Found invalid ListViewItem." ) );
		}
	}
}

void KMFListView::slotUpdateView() {
	if ( ! m_NetfilterObject )
		return ;
	if ( ! KMFAppState::upAndRunning() ) {
		kdDebug() << "Doing Nothing during startup." << endl;
		this->clearAllItems();
		return;
	}
	if ( ! KMFAppState::hasOpenDoc() ) {
		kdDebug() << "No Open doc. disabling view!" << endl;
		this->clearAllItems();
		setEnabled( false );
		return;
	}
	setEnabled( true );
	emit sigLoadNode( m_NetfilterObject );
}

void KMFListView::slotUpdateView( NetfilterObject* obj ) {
	if ( ! obj )
		return;
	if ( ! KMFAppState::upAndRunning() ) {
		kdDebug() << "Doing Nothing during startup." << endl;
		this->clearAllItems();
		return;
	}
	if ( obj->type() == NetfilterObject::TABLE ) {
		if ( ! m_NetfilterObject )
		return ;
		emit sigLoadNode( m_NetfilterObject );
	} else if ( obj->type() == NetfilterObject::CHAIN ) {
		if ( IPTChain* chain = dynamic_cast<IPTChain*>( obj ) ) {
			if ( KMFListViewItem* item = findKMFItem( chain->name(), 2, chain->objectID()) ) {
				if ( KMFListViewItem* parent = dynamic_cast<KMFListViewItem*>( item->parent() ) ) {
					emit sigLoadNode( m_NetfilterObject );
// 					kdDebug() << "\nStarting update for Chain Item..." << endl;
					setUpdatesEnabled( false );
					setupChainView( chain, parent );
					setUpdatesEnabled( true );
					triggerUpdate();
// 					kdDebug() << "Finished update for Chain Item.\n" << endl;
				}
			}
		}
	} else if ( obj->type() == NetfilterObject::RULE  ) {
		if ( IPTRule* rule = dynamic_cast<IPTRule*>( obj ) ) {
			if ( KMFListViewItem* item = findKMFItem( rule->name(), 2, rule->objectID()) ) {
				if ( KMFListViewItem* parent = dynamic_cast<KMFListViewItem*>( item->parent() ) ) {
// 					kdDebug() << "\nStarting update for Rule Item..." << endl;
					setUpdatesEnabled( false );
					setupRuleView( rule, parent );
					setUpdatesEnabled( true );
					triggerUpdate();
// 					kdDebug() << "Finished update for Rule Item.\n" << endl;
				}
			}
		}
	}
}

KMFListViewItem* KMFListView::getRootItem() {
	KMFListViewItem * item = dynamic_cast<KMFListViewItem*>( firstChild() );
	if ( item ) {
		return item;
	} else {
		return 0;
	}
}

void KMFListView::slotChangeRoot( QListViewItem* /*item*/ ) {
	// 	if ( ! item || item == 0)
	// 		return;
	//
	// 	if ( KMFListViewItem * tmp_item = dynamic_cast<KMFListViewItem *>( item ) ) {
	// 		if ( tmp_item == 0 || ! tmp_item )
	// 			return ;
	// 		if ( tmp_item->isTopItem() && tmp_item->type() == KMFListViewItem::RULEOPTION )
	// 			if ( tmp_item->ruleOption() )
	// 				emit sigLoadNode( tmp_item->ruleOption() );
	// 		if ( tmp_item->isTopItem() && tmp_item->type() == KMFListViewItem::RULE )
	// 			if ( tmp_item->rule() )
	// 				emit sigLoadNode( tmp_item->rule() );
	// 		if ( tmp_item->isTopItem() && tmp_item->type() == KMFListViewItem::CHAIN )
	// 			if ( tmp_item->chain() )
	// 				emit sigLoadNode( tmp_item->chain() );
	// 		if ( tmp_item->isTopItem() && tmp_item->type() == KMFListViewItem::TABLE )
	// 			if ( tmp_item->table() )
	// 				emit sigLoadNode( tmp_item->table() );
	// 	}
}

void KMFListView::setupTableView( IPTable* table ) {
//	kdDebug() << "KMFListView::setupTableView(IPTable* table, KMFListViewItem* item )" << endl;
	if ( ! table )
		return ;
	KMFListViewItem* item = 0;
	item = findKMFItem( i18n( "Table:" ), 0, table->objectID() );
	if ( ! item ) {
		item = new KMFListViewItem( this, 0, table );
		item->setOpen( true );
	}
	item->sortChildItems( 0, true );
	item->setTopItem( true );
	item->setInUse( true );
	item->setOpen( true );
	item->setText( 0, i18n( "Table:" ) );
	item->setPixmap( 0 , icon_table );
	item->setText( 2, table->name() );

	QPtrList<IPTChain> chains = table->chains();
	QPtrList<IPTChain> used_chains;
	for ( int i = chains.count(); i >= 0; i-- ) {
		IPTChain* chain = 0;
		chain = chains.at( i );
		if ( chain ) {
			used_chains.append ( chain );
			QString str_obj_id = "";
			str_obj_id =  str_obj_id.setNum( chain->objectID() );

			if ( m_existed_chains.findIndex ( chain->name() + "|" + str_obj_id ) == -1 )
				m_existed_chains.append ( chain->name() + "|" + str_obj_id );

			if ( ! m_dict_existed_rules.find( chain->objectID() ) ) {
				m_dict_existed_rules.insert( chain->objectID(), new QStringList );
			}
			setupChainView( chain, item );
		}
	}
	if ( ! m_existed_chains.isEmpty() ) {
		for ( QStringList::Iterator it = m_existed_chains.begin(); it != m_existed_chains.end(); ++it ) {
			QString existed_chain_name_id = *it;
			int delimiter = existed_chain_name_id.find( "|" );
			QString existed_chain_name = existed_chain_name_id.left( delimiter );
			QString existed_chain_id_str = existed_chain_name_id.right( existed_chain_name_id.length() - delimiter - 1 );
			int existed_obj_id = -1;
			bool ok;
			existed_obj_id = existed_chain_id_str.toInt( &ok );
// 			kdDebug() << "Found Existed Name: " << existed_chain_name << " ID: " << existed_obj_id << endl;
			bool have = false;
			QPtrListIterator<IPTChain> it2( used_chains );
			IPTChain* used_chain = 0;
			while ( it2.current() ) {
				used_chain = it2.current();
// 				kdDebug() << "Entering: while ( used_chain )" << endl;
				++it2;
				if ( existed_chain_name == used_chain->name() ) {
// 					kdDebug() << "Chain: " << used_chain->name() << " already existed:" << endl;
					have = true;
				}
			}
			if ( ! have ) {
// 				kdDebug() << "Chain: " << existed_chain_name << " could not be found" << endl;
				KMFListViewItem* del_item = findKMFItem( existed_chain_name, 2, existed_obj_id );
				if ( del_item ) {
// 					kdDebug() << "Chain: " << existed_chain_name << " was DELETED:" << endl;
					delete del_item;
				}
			}
		}
	}

	m_existed_chains.clear();
	QPtrListIterator<IPTChain> it3 ( used_chains );
	while ( it3.current() ) {
		IPTChain * chain = it3.current();
		++it3;
		QString str_obj_id = "";
		str_obj_id =  str_obj_id.setNum( chain->objectID() );

		m_existed_chains.append( chain->name() + "|" +  str_obj_id );
	}

	KMFListViewItem * item_desc = 0;
	item_desc = findKMFItem( i18n( "Documentation:" ), 0, table->objectID() );

	if ( !table->description().isEmpty() && m_show_desc ) {
		if ( ! item_desc ) {
			item_desc = new KMFListViewItem( item, 0, table );
		}

		item_desc->setInUse( true );
		item_desc->setMultiLinesEnabled( true );
		item_desc->setText( 0, i18n( "Documentation:" ) );
		item_desc->setPixmap( 1, icon_rename );
		item_desc->setText( 2, table->description() );

	} else if ( item_desc ) {
		delete item_desc;
	}

	
	KMFListViewItem* item_obj_id = 0;
	item_obj_id = findKMFItem( i18n( "Object ID:" ), 0, table->objectID(),true,item );
	
	if  ( KMFConfig::showObjectID() ) {
		if ( ! item_obj_id ) {
			item_obj_id = new KMFListViewItem( item, 0, table );
		}
		item_obj_id->setInUse( true );
		item_obj_id->setText( 0, i18n( "Object ID:" ) );
		QString sid = "";
		item_obj_id->setText( 2, sid.setNum( table->objectID() ) );
	} else if ( item_obj_id ) {
		delete item_obj_id;
	}
// 	kdDebug() << "Sorting Table Item Children..." << endl;
	item->sort();
}

void KMFListView::setupChainView( IPTChain* chain, KMFListViewItem* parent ) {
// 	kdDebug() << "KMFListView::setupChainView( IPTChain* chain, KMFListViewItem* item )" << endl;
	if ( ! chain || ! parent )
		return ;

	KMFListViewItem * item = 0;
	item = findKMFItem( chain->name(), 2, chain->objectID(), true, parent );
	if ( ! item ) {
// 		kdDebug() << "No Item for Chain: " << chain->name() << " found.\nNeed to create a new one." << endl;
		item = new KMFListViewItem( parent, 0, chain );
	}
	item->sortChildItems( 0, true );
	item->setTopItem( true );
	item->setInUse( true );
	QPixmap icon_null;
	item->setText( 0, i18n( "Chain:" ) );
	if ( chain->isBuildIn() ) {
		item->setPixmap( 0, icon_builtin );
	} else {
		item->setPixmap( 0, icon_user );
	}
	
	if ( chain->logging() ) {
		item->setPixmap( 1, icon_log );
	} else {
		item->setPixmap( 1, icon_null );
	}
	QString chain_name = chain->name();
	item->setText( 2, chain_name );


	KMFListViewItem * i_chain_cmd = 0;
	i_chain_cmd = findKMFItem( i18n( "Cmd:" ), 0, chain->objectID(), true, item );

	if ( ! chain->isBuildIn() && m_show_cmds ) {
		if ( ! i_chain_cmd ) {
			i_chain_cmd = new KMFListViewItem( item , 0, chain );
		}
		QString tmp_cmd = chain->createIPTablesChainDefinition();
		//		kdDebug() << "Setting up item: i_chain_cmd" << endl;
		i_chain_cmd->setInUse( true );
		i_chain_cmd->setText( 0, i18n( "Cmd:" ) );
		i_chain_cmd->setPixmap( 0, icon_cmd );
		i_chain_cmd->setText( 2, tmp_cmd );
	} else if ( i_chain_cmd ) {
		delete i_chain_cmd;
	}

	// logging+++++++++++++++++++++++++++++++++++++++++++++++++++
	//	kdDebug() << "Setting up item: i_chain_log" << endl;
	bool logging = chain->logging();
	KMFListViewItem * i_chain_log = 0;
	i_chain_log = findKMFItem( i18n( "Chain logging:" ), 0, chain->objectID(), true, item );

	if ( ! logging && i_chain_log ) {
		delete i_chain_log;
	}

	if ( logging ) {
		if ( ! i_chain_log ) {
			i_chain_log = new KMFListViewItem( item, 0, chain );
			i_chain_log->setOpen( true );
		}
		i_chain_log->setInUse( true );
		i_chain_log->setText( 0, i18n( "Chain logging:" ) );
		//    	kdDebug() << "Logging enabled" << endl;
		//		i_chain_log->setPixmap( 1, icon_log );
		i_chain_log->setText( 2, i18n( "Dropped Packets" ) );
		QString limit = chain->logLimit();
		QString prefix = chain->logPrefix();
		QString burst = chain->logBurst();
		KMFListViewItem * i_limit = 0;
		i_limit = findKMFItem( i18n( "Limit rate:" ), 0, chain->objectID(), true, i_chain_log );


		if ( limit.isEmpty() && i_limit ) {
			delete i_limit;
		} else
			if ( ! limit.isEmpty() ) {
				if ( ! i_limit ) {
					i_limit = new KMFListViewItem( i_chain_log, 0, chain );
					i_limit->setOpen( true );
				}

				i_limit->setInUse( true );
				i_limit->setText( 0, i18n( "Limit rate:" ) );
				i_limit->setText( 2, limit );

				KMFListViewItem * i_burst = 0;
				i_burst = findKMFItem( i18n( "Limit burst:" ), 0, chain->objectID(), true, i_chain_log );

				if ( burst.isEmpty() && i_burst ) {
					delete i_burst;
				}

				if ( ! burst.isEmpty() ) {
					//			 kdDebug() << "Setting up item: i_burst" << endl;
					if ( ! i_burst ) {
						i_burst = new KMFListViewItem( i_chain_log, i_limit, chain );
						i_burst->setOpen( true );
					}
					i_burst->setInUse( true );
					i_burst->setText( 0, i18n( "Limit burst:" ) );
					i_burst->setText( 2, burst );
				}
			}

		KMFListViewItem* i_prefix = 0;
		i_prefix = findKMFItem( i18n( "Log prefix:" ), 0, chain->objectID(), true, i_chain_log );

		if ( prefix.isEmpty() && i_prefix ) {
// 			i_prefix->setInUse( false );
			delete i_prefix;
		}

		if ( ! prefix.isEmpty() ) {
			// 			kdDebug() << "Setting up item: i_prefix" << endl;
			if ( ! i_prefix ) {
				i_prefix = new KMFListViewItem( i_chain_log, 0, chain );
				i_prefix->setOpen( true );
			}
			i_prefix->setInUse( true );
			i_prefix->setText( 0, i18n( "Log prefix:" ) );
			i_prefix->setText( 2, prefix );

		}
	}

	//  // chain feeds++++++++++++++++++++++++++++++++++++++++++++
	QString str = chain->name();
	QPtrList<IPTRule> feeds = chain->chainFeeds();
	bool buildin = chain->isBuildIn();
	//	kdDebug() << "Setting up item: i_chain_feeds" << endl;
	KMFListViewItem * i_chain_feeds = 0;
	i_chain_feeds = findKMFItem( i18n( "Chain Feeds:" ), 0, chain->objectID(), true, item );
	if ( ! i_chain_feeds ) {
		if ( logging )
			i_chain_feeds = new KMFListViewItem( item, i_chain_log, chain );
		else
			i_chain_feeds = new KMFListViewItem( item, item, chain );
		i_chain_feeds->setOpen( true );
	}
	i_chain_feeds->setText( 0, i18n( "Chain Feeds:" ) );
	i_chain_feeds->setInUse( true );
	if ( buildin ) {
		i_chain_feeds->setText( 2, i18n( "System Feed" ) );
	} else {
		int number = feeds.count();
		QString num_feed = i18n( "1 Feed", "%n Feeds", number );
		i_chain_feeds->setText( 2, num_feed );
		i_chain_feeds->setInUse( true );
		i_chain_feeds->deleteChildren();
		IPTRule *curr_rule = 0;
		QPtrList<KMFListViewItem> used_items;
		if ( ! feeds.isEmpty() ) {
			i_chain_feeds->setPixmap( 0, icon_feed );
			QPtrListIterator<IPTRule> it( feeds );
			while ( it.current() ) {
				curr_rule = it.current();
				++it;
				KMFListViewItem * item_feeds = new KMFListViewItem( i_chain_feeds, chain );
				item_feeds->setInUse( true );
				item_feeds->setText( 0, i18n( "From chain: %1" ).arg( curr_rule->chain() ->name() ) );
				item_feeds->setPixmap( 2, icon_rule );
				item_feeds->setText( 2, curr_rule->name() );
			}
		}
	}
	//  //chain fwds++++++++++++++++++++++++++++++++++++++++++++++++
	QPtrList<IPTRule> fwds = chain->chainFwds();

	//	kdDebug() << "Setting up item: i_chain_fwds" << endl;
	KMFListViewItem * i_chain_fwds = 0;
	i_chain_fwds = findKMFItem( i18n( "Chain forwards:" ), 0, chain->objectID(), true, item );
	if ( ! i_chain_fwds ) {
		i_chain_fwds = new KMFListViewItem( item, i_chain_feeds, chain );
		i_chain_fwds->setOpen( true );
	}

	int number2 = fwds.count();
	QString num_fwd = i18n( "1 Forward", "%n Forwards", number2 );
	i_chain_fwds->setInUse( true );
	i_chain_fwds->setText( 0, i18n( "Chain forwards:" ) );
	i_chain_fwds->setText( 2, num_fwd );

// 	QPtrList<KMFListViewItem> used_items;
	i_chain_fwds->deleteChildren();
	if ( !fwds.isEmpty() ) {
		i_chain_fwds->setPixmap( 0, icon_fwds );
		IPTRule * curr_rule;
		QPtrListIterator<IPTRule> it( fwds );
		while ( it.current() ) {
			curr_rule = it.current();
			++it;
			KMFListViewItem * item_fwds = new KMFListViewItem( i_chain_fwds, chain );
			item_fwds->setInUse( true );
			item_fwds->setPixmap( 0, icon_rule );
			item_fwds->setText( 0, i18n( "Rule: %1" ).arg( curr_rule->name() ) );
			item_fwds->setPixmap( 1, icon_fwd );
			item_fwds->setText( 2, curr_rule->target() );
		}
	}


	//########### Start Rules ####################
	QPtrList<IPTRule> tmp_ruleset = chain->chainRuleset();

	//	kdDebug() << "Setting up item: i_chain_allrules" << endl;
	KMFListViewItem* i_chain_allrules = 0;
	i_chain_allrules = findKMFItem( i18n( "Rule(s):" ), 0, chain->objectID(), true, item );
	if ( ! i_chain_allrules ) {
		i_chain_allrules = new KMFListViewItem( item, i_chain_fwds, chain );
		i_chain_allrules->setOpen( TRUE );
	}
	i_chain_allrules->sortChildItems( 0, true );

	int number3 = tmp_ruleset.count();
	QString num_rules = i18n( "1 Rule", "%n Rules", number3 );
	i_chain_allrules->setInUse( true );
	i_chain_allrules->setText( 0, i18n( "Rule(s):" ) );
	i_chain_allrules->setPixmap( 0, icon_rule );
	i_chain_allrules->setText( 2, num_rules );

	QPtrList<IPTRule> used_rules;
	QStringList *existed_rules = m_dict_existed_rules.find( chain->objectID() );

	if ( existed_rules ) {
		if ( !tmp_ruleset.isEmpty() ) {
			IPTRule * curr_rule;
			for ( curr_rule = tmp_ruleset.last(); curr_rule; curr_rule = tmp_ruleset.prev() ) {
// 				kdDebug() << "Entering: for ( curr_rule = tmp_ruleset.last(); curr_rule; curr_rule = tmp_ruleset.prev() )" << endl;
				used_rules.append( curr_rule );
				QString str_obj_id = "";
				str_obj_id =  str_obj_id.setNum( curr_rule->objectID() );
				if ( existed_rules->findIndex ( curr_rule->name() + "|" + str_obj_id ) == -1 ) {
					existed_rules->append( curr_rule->name() + "|" + str_obj_id );
				}
				setupRuleView( curr_rule , i_chain_allrules );
			}
		}
		if ( ! existed_rules->isEmpty() )
			for ( QStringList::Iterator it = existed_rules->begin(); it != existed_rules->end(); ++it ) {
				QString existed_rule_name_id = *it;
				int delimiter = existed_rule_name_id.find( "|" );
				QString existed_rule_name = existed_rule_name_id.left( delimiter );
				QString existed_rule_id_str = existed_rule_name_id.right( existed_rule_name_id.length() - delimiter - 1 );
				int existed_obj_id = -1;
				bool ok;
				existed_obj_id = existed_rule_id_str.toInt( &ok );
// 				kdDebug() << "Found Existed Name: " << existed_rule_name << " ID: " << existed_obj_id << endl;
				bool have = false;
				QPtrListIterator<IPTRule> it2( used_rules );
				IPTRule* used_rule = 0;
				while ( it2.current() ) {
					used_rule = it2.current();
// 					kdDebug() << "Entering: while ( used_rule )" << endl;
					++it2;
					if ( /*existed_rule_name == used_rule->name() &&*/ existed_obj_id == used_rule->objectID() ) {
 						kdDebug() << "Rule: " << used_rule->name() << " already existed." << endl;
						have = true;
					}
				}
				if ( ! have ) {
// 					kdDebug() << "Rule: " << existed_rule_name << " could not be found" << endl;
					KMFListViewItem* del_item = findKMFItem( existed_rule_name, 2, existed_obj_id );
					if ( del_item ) {
// 						kdDebug() << "Rule: " << existed_rule_name << " was DELETED:" << endl;
						delete del_item;
					} else {
						del_item = findKMFItem( i18n("Rule"), 0, existed_obj_id, false );
						if ( del_item ) {
// 							kdDebug() << "Rule: " << existed_rule_name << " was DELETED:" << endl;
							delete del_item;
						}
					}
				}
			}

		existed_rules->clear();

		QPtrListIterator<IPTRule> it3 ( used_rules );
		while ( it3.current() ) {
			IPTRule * rule = it3.current();
			++it3;
			QString str_obj_id = "";
			existed_rules->append( rule->name() + "|" + str_obj_id.setNum( rule->objectID() ) );
		}
	}
	//########### End Rules ####################

	// default target ++++++++++++++++++++++++++++++++++++

	KMFListViewItem * i_deftg = 0;
	i_deftg = findKMFItem( i18n( "Target:" ), 0, chain->objectID(), true, item );
	if ( ! i_deftg ) {
		i_deftg = new KMFListViewItem( item, i_chain_allrules, chain );
	}

	if ( ! chain->hasDefaultTarget() ) {
		delete i_deftg;
	} else {
		QString def_tg = chain->defaultTarget();
		QString cmd = chain->createIPTablesChainDefaultTarget();

		//		kdDebug() << "Setting up item: i_deftg" << endl;
		i_deftg->setInUse( true );
		i_deftg->setPixmap( 0, icon_target );
		i_deftg->setText( 0, i18n( "Target:" ) );
		i_deftg->setText( 2, def_tg );
		kdDebug() << "Target: " << cmd << endl;
		if ( def_tg == "DROP" ) {
			i_deftg->setPixmap( 1, icon_drop );
		} else if ( def_tg == "ACCEPT" ) {
			i_deftg->setPixmap( 1, icon_accept );
		}

		//		kdDebug() << "Setting up item: i_deftg_rule" << endl;
		KMFListViewItem * i_deftg_rule = 0;
		i_deftg_rule = findKMFItem( i18n( "Policy Cmd:" ), 0, chain->objectID(), true, i_deftg );

		if ( m_show_cmds ) {
			if ( ! i_deftg_rule ) {
					i_deftg_rule = new KMFListViewItem( i_deftg, chain );
					i_deftg_rule->setOpen( false );
				}
			i_deftg_rule->setInUse( true );
			i_deftg_rule->setText( 0, i18n( "Policy Cmd:" ) );
			i_deftg_rule->setPixmap( 0, icon_cmd );
			i_deftg_rule->setText( 2, cmd );
		} else {
			if ( i_deftg_rule )
				delete i_deftg_rule;
		}
	}

	KMFListViewItem * item_desc = 0;
	item_desc = findKMFItem( i18n( "Documentation:" ), 0, chain->objectID(), true, item  );

	if ( !chain->description().isEmpty() && ! chain->isBuildIn() ) {
		if ( ! item_desc ) {
			item_desc = new KMFListViewItem( item, item, chain );
		}
		item_desc->setInUse( true );
		item_desc->setMultiLinesEnabled( true );
		item_desc->setText( 0, i18n( "Documentation:" ) );
		item_desc->setPixmap( 1, icon_rename );
		item_desc->setText( 2, chain->description() );

	} else if( !chain->description().isEmpty() &&  chain->isBuildIn() && m_show_desc ) {
		if ( ! item_desc ) {
			item_desc = new KMFListViewItem( item, item, chain );
		}
		item_desc->setInUse( true );
		item_desc->setMultiLinesEnabled( true );
		item_desc->setText( 0, i18n( "Documentation:" ) );
		item_desc->setPixmap( 1, icon_rename );
		item_desc->setText( 2, chain->description() );
	} else if ( item_desc ) {
		delete item_desc;
	}
	
	KMFListViewItem* item_obj_id = 0;
	item_obj_id = findKMFItem( i18n( "Object ID:" ), 0, chain->objectID(),true,item );
	
	if  ( KMFConfig::showObjectID() ) {
		if ( ! item_obj_id ) {
			item_obj_id = new KMFListViewItem( item, 0, chain );
		}
		item_obj_id->setInUse( true );
		item_obj_id->setText( 0, i18n( "Object ID:" ) );
		QString sid = "";
		item_obj_id->setText( 2, sid.setNum( chain->objectID() ) );
	} else if ( item_obj_id ) {
		delete item_obj_id;
	}	
// 	kdDebug() << "Sorting Chain Item Children...\n" << endl;
	item->sort();
}

void KMFListView::setupRuleView( IPTRule* rule, KMFListViewItem* parent ) {
// 	kdDebug() << "KMFListView::setupRuleView( IPTRule* rule, KMFListViewItem* item )" << endl;
	if ( ! rule || ! parent )
		return ;

	KMFListViewItem * item = 0;
	item = findKMFItem( rule->name(), 2, rule->objectID(), true, parent );
	if ( ! item ) {
//		kdDebug() << "No Item for Rule: " << rule->name() << " found.\nNeed to create a new one." << endl;
		item = new KMFListViewItem( parent, parent, rule );
	}
	item->sortChildItems( 0, true );
	item->setTopItem( true );
	item->setInUse( true );
	QPixmap icon_null;
	QString rule_name = rule->name();
	QString rule_target = rule->target();
	QString rule_cmd = rule->toString();

	QString rule_nr = "";
	if ( rule->customRule() && rule->enabled() ) {
		rule_nr = rule_nr + "Custom ";
	}
	if ( !rule->enabled() ) {
		rule_nr = rule_nr + "Disabled ";
	}
	rule_nr = rule_nr + "Rule:";
	QString rule_number = "";
	rule_number = rule_number.setNum( rule->ruleNum() +1 );
	rule_nr = rule_nr + " " + rule_number;
// 	item->setPixmap( 0, icon_rule );
	item->setText( 0, rule_nr );
	if ( ! rule->enabled() )
		item->setPixmap( 0, icon_disabled );
	else if ( rule->logging() )
		item->setPixmap( 0, icon_log );
	else
		item->setPixmap( 0, icon_rule );

	item->setText( 1, QString::null );
	item->setPixmap( 2, icon_null );
	item->setText( 2, rule_name );
	item->setRenameEnabled( 2, true );

	//	kdDebug() << "There are options defined for the rule " << endl;
	KMFListViewItem* item_target = 0;
	item_target = findKMFItem( i18n( "Target:" ), 0, rule->objectID(), true, item );
	if ( !item_target ) {
		item_target = new KMFListViewItem( item, 0, rule );
	}
	item_target->setInUse( true );
	item_target->setText( 0, i18n( "Target:" ) );
	item_target->setPixmap( 0, icon_target );
	item_target->setText( 2, rule_target );
	if ( rule_target == "ACCEPT" ) {
		item_target->setPixmap( 1, icon_accept );
	} else if ( rule_target == "DROP" ) {
		item_target->setPixmap( 1, icon_drop );
	} else if ( rule_target == "LOG" ) {
		item_target->setPixmap( 1, icon_log );
	} else if ( rule_target == "REJECT" ) {
		item_target->setPixmap( 1, icon_reject );
	} else if ( rule_target == "RETURN" ) {
		item_target->setPixmap( 1, icon_return );
	} else if ( rule_target == "QUEUE" ) {
		item_target->setPixmap( 1, icon_queue );
	}

	KMFListViewItem* item_cmd = 0;
	item_cmd = findKMFItem( i18n( "Cmd:" ), 0, rule->objectID(), true, item );

	if ( m_show_cmds ) {
		if ( ! item_cmd ) {
			item_cmd = new KMFListViewItem( item, 0, rule );
		}
		item_cmd->setInUse( true );
		item_cmd->setMultiLinesEnabled( true );
		item_cmd->setText( 0, i18n( "Cmd:" ) );
		item_cmd->setPixmap( 0, icon_cmd );
		item_cmd->setText( 2, rule_cmd );
	} else if ( item_cmd ) {
		delete item_cmd;
	}

	//############## Start Rule Options ############
	QPtrList<QString>* available_options = IPTRuleOption::getAvailableOptionTypes();
	for ( uint j = 0;j < available_options->count();j++ ) {
		QString type = "";
		type = *available_options->at( j );
		if ( type.isEmpty() )
			return ;

		IPTRuleOption* opt = 0;
		opt = rule->getOptionForName( type );
		if ( ! opt ) {
			return ;
		}
		
// 		kdDebug() << "Found Option: " << opt->guiName() << " is emty "<< opt->isEmpty() << endl;
		
		if ( ! opt->isEmpty() ) {
			if ( !opt->isTargetOption() ) {
				setupRuleOptionView( opt, item );
			} else if ( opt->isTargetOption() ) {
				setupRuleOptionView( opt, item_target );
			}
		} else {

			KMFListViewItem * kmfitem = 0;
			kmfitem = findKMFItem( opt->guiName(), 0, opt->objectID(), true, item );
			if ( kmfitem ) {
				delete kmfitem;
			} else {
				kmfitem = findKMFItem( opt->guiName(), 0, opt->objectID(), true, item_target );
				if ( kmfitem ) {
					delete kmfitem;
				}
			}


		}
	}
	//############## End Rule Options ############

	KMFListViewItem * item_log = 0;
	item_log = findKMFItem( i18n( "Logging:" ), 0, rule->objectID(),true,item );
	if ( rule->logging() && ! rule->enabled() ) {
		if ( ! item_log ) {
			item_log = new KMFListViewItem( item, 0, rule );
		}
		item_log->setInUse( true );
		item_log->setText( 0, i18n( "Logging:" ) );
		item_log->setPixmap( 1, icon_log );
		item_log->setText( 2, i18n( "Logging matching Packets" ) );
	} else if ( item_log ) {
		delete item_log;
	}


	KMFListViewItem * item_desc = 0;
	item_desc = findKMFItem( i18n( "Documentation:" ), 0, rule->objectID(),true,item );

	if ( !rule->description().isEmpty() ) {
		if ( ! item_desc ) {
			item_desc = new KMFListViewItem( item, 0, rule );
		}

		item_desc->setInUse( true );
		item_desc->setMultiLinesEnabled( true );
		item_desc->setText( 0, i18n( "Documentation:" ) );
		item_desc->setPixmap( 1, icon_rename );
		item_desc->setText( 2, rule->description() );

	} else if ( item_desc ) {
		delete item_desc;
	}
	
	KMFListViewItem* item_obj_id = 0;
	item_obj_id = findKMFItem( i18n( "Object ID:" ), 0, rule->objectID(),true,item );

	if  ( KMFConfig::showObjectID() ) {
		if ( ! item_obj_id ) {
			item_obj_id = new KMFListViewItem( item, 0, rule );
		}
		item_obj_id->setInUse( true );
		item_obj_id->setText( 0, i18n( "Object ID:" ) );
		QString sid = "";
		item_obj_id->setText( 2, sid.setNum( rule->objectID() ) );
	} else if ( item_obj_id ) {
		delete item_obj_id;
	}
	item->sort();
}

void KMFListView::setupRuleOptionView( IPTRuleOption* option, KMFListViewItem* parent ) {
// 	kdDebug() << "void KMFListView::setupRuleOptionView( IPTRuleOption* option, KMFListViewItem* parent )" << endl;
	if ( ! option || ! parent )
		return ;

	QString type = option->getOptionType();
	QStringList values = option->getValues();
	QDict<QStringList>* gui_string_dict = option->getGUIStringDict();
	QStringList* gui_strings = gui_string_dict->find( type );
	QString name = "";
	
	KMFListViewItem * item = 0;
	item = findKMFItem( option->guiName(), 0, option->objectID(),true,parent );
	
	if ( values.count() < 1 || option->isEmpty() ) {
		if ( item ) {
			delete item;
		}
		return;	
	}

	if ( ! item ) {
// // 		kdDebug() << "No Item for Option: " << *gui_strings->at( 0 ) << " found.\nCreateing a new one." << endl;
		item = new KMFListViewItem( parent, parent, option );
		item->setOpen( true );
	}
	
	item->setTopItem( true );
	item->setInUse( true );
	item->setPixmap( 0, icon_filter );
	item->setText( 0, option->guiName() );

	// 		KMFListViewItem* item_filter = 0;
	for ( uint i = 0; i < values.count(); i++ ) {
		QString val = "";
		val = *values.at( i );
		if ( val.isNull() )
			return ;


		if ( gui_strings->count() > i /* + 1 */ ) {
			// 			if (val == "bool:on")
			// 				val = "";

			QString gui_name = "";
			gui_name = *gui_strings->at( i  /* + 1 */ );
			KMFListViewItem * item_opt = 0;
			item_opt = findKMFItem( gui_name, 0, option->objectID(),true,item );

			if ( gui_name.isEmpty() || val == "UNDEFINED" || val.simplifyWhiteSpace().isEmpty() || val == "bool:off" ) {
				if ( item_opt ) {
					delete item_opt;
				}
			} else {
				if ( ! item_opt ) {
// 					kdDebug() << "Creating Item for option Name: " << gui_name << endl;
					item_opt = new KMFListViewItem( item, 0, option );
					item_opt->setOpen( true );
				}
				if ( val != "bool:on" ) {
					item_opt->setInUse( true );
					item_opt->setText( 0, gui_name );
					item_opt->setText( 2, val );
				} else {
					item_opt->setInUse( true );
					item_opt->setText( 0, gui_name );
				}
			}
		}
	}
	
	KMFListViewItem *item_obj_id = 0;
	item_obj_id = findKMFItem( i18n( "Object ID:" ), 0, option->objectID(),true,item );
	if  ( KMFConfig::showObjectID() ) {
		if ( ! item_obj_id ) {
			item_obj_id = new KMFListViewItem( item, 0, option );
		}
		item_obj_id->setInUse( true );
		item_obj_id->setText( 0, i18n( "Object ID:" ) );
		QString sid = "";
		item_obj_id->setText( 2, sid.setNum( option->objectID() ) );
	} else if ( item_obj_id ) {
		delete item_obj_id;
	}
}

void KMFListView::clearAllItems() {
// 	kdDebug() << "void KMFListView::clearAllItems()" << endl;
/*	m_existed_chains.clear();
	m_dict_existed_rules.clear();*/
	clear();
}

KMFListViewItem* KMFListView::findKMFItem( const QString & text, int column, int obj_id, bool exact /*= true*/, KMFListViewItem* from_item /*= 0*/  ) {
	// 	kdDebug() << "KMFListViewItem* KMFListView::findKMFItem(const QString& text: " << text << ", int column:" << column << ", int obj_id: " << obj_id << ")" << endl;
	if ( text.isNull() || column < 0 || obj_id < -1 )
		return 0;
	if ( from_item ) {
// 		from_item->setText(1,"Serching this item");
		QListViewItemIterator it( from_item );
		QListViewItem * qitem = 0;

		qitem = from_item->firstChild();
		while ( qitem ) {
			KMFListViewItem * item = 0;
			item = dynamic_cast<KMFListViewItem*> ( qitem );
			if ( item ) {
// 				item->setPixmap(1,icon_accept);
				if ( exact ) {
					if ( item->text( column ) == text && item->objectID() == obj_id )
						return item;
				} else {
					if ( item->text( column ).contains( text ) && item->objectID() == obj_id )
						return item;
				}
			} else {
				kdDebug() << "CAST ERROR: Item not of type KMFListViewItem" << endl;
				return 0;
			}
			qitem = qitem->nextSibling();
		}
	} else {
		QListViewItemIterator it( this );
		while ( it.current() ) {
			QListViewItem * qitem = it.current();
			++it;
			KMFListViewItem * item = 0;
			item = dynamic_cast<KMFListViewItem*> ( qitem );
			if ( item ) {
				if ( exact ) {
					if ( item->text( column ) == text && item->objectID() == obj_id )
						return item;
				} else {
					if ( item->text( column ).contains( text ) && item->objectID() == obj_id )
						return item;
				}
			} else {
				kdDebug() << "CAST ERROR: Item not of type KMFListViewItem" << endl;
			}
		}
	}
// 	kdDebug() << "Couldn't find Item " << text << "  column: " << column << ", int obj_id: " << obj_id << endl;
	return 0;
}

KMFListViewItem* KMFListView::findKMFItem( const QString & text1, int column1,const QString & text2, int column2, int obj_id ) {
	// 	kdDebug() << "KMFListViewItem* KMFListView::findKMFItem(const QString& text: " << text << ", int column:" << column << ", int obj_id: " << obj_id << ")" << endl;
	if ( text1.isNull() || column1 < 0 || obj_id < -1 || text2.isNull() || column2 < 0 )
		return 0;

	QListViewItemIterator it( this );
	while ( it.current() ) {
		QListViewItem * qitem = it.current();
		++it;
		KMFListViewItem * item = 0;
		item = dynamic_cast<KMFListViewItem*> ( qitem );
		if ( item ) {
			if ( item->text( column1 ) == text1 &&   item->text( column2 ) == text2 && item->objectID() == obj_id )
				return item;
		} else {
			kdDebug() << "CAST ERROR: Item not of type KMFListViewItem" << endl;
		}
	}
// 	kdDebug() << "Couldn't find Item " << text << "  column: " << column << ", int obj_id: " << obj_id << endl;
	return 0;
}


void KMFListView::loadIcons() {
	kdDebug() << "void KMFListView::loadIcons()" << endl;
	KIconLoader *loader = KGlobal::iconLoader();
	QString icon_name;

	icon_name = "up";
	icon_up = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "down";
	icon_down = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "ereaser";
	icon_del = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "filenew";
	icon_new = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "edit";
	icon_edit = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "rule";
	icon_rule = loader->loadIcon( icon_name, KIcon::Small );
	
	icon_name = "user_defined";
	icon_user = loader->loadIcon( icon_name, KIcon::Small );
	
	icon_name = "builtin";
	icon_builtin = loader->loadIcon( icon_name, KIcon::Small );
	
	icon_name = "table";
	icon_table = loader->loadIcon( icon_name, KIcon::Small );
	
	icon_name = "filter";
	icon_filter = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "text";
	icon_rename = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "view_tree";
	icon_chain = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "reject";
	icon_reject = loader->loadIcon( icon_name, KIcon::User );

	icon_name = "target";
	icon_target = loader->loadIcon( icon_name, KIcon::User );

	icon_name = "stop";
	icon_drop = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "button_ok";
	icon_accept = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "filesaveas";
	icon_log = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "undo";
	icon_return = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "editclear";
	icon_cmd = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "filter";
	icon_filter = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "pipe";
	icon_queue = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "button_cancel";
	icon_disabled = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "1rightarrow";
	icon_fwd = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "2rightarrow";
	icon_fwds = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "fill";
	icon_feed = loader->loadIcon( icon_name, KIcon::Small );

}




#include "kmflistview.moc"
