//
// C++ Implementation: kmfgenericinterfaceeditprotocol
//
// Description:
//
//
// Author: Christian Hubinger <chubinger@irrsinnig.org>, (C) 2003
//
// Copyright: See COPYING file that comes with this distribution
//
//
/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/


#include "kmfgenericinterfaceeditprotocol.h"

// TQt includes
#include <tqstring.h>
#include <tqcheckbox.h>
#include <tqfile.h>
#include <tqdir.h>
#include <tqdom.h>
#include <tqstring.h>
#include <tqstringlist.h>
#include <tqlistview.h>
#include <tqradiobutton.h>
#include <tqpushbutton.h>
#include <tqlineedit.h>
#include <tqtextedit.h>
#include <tqbuttongroup.h>
#include <tqgroupbox.h>
#include <tqspinbox.h>
#include <tquuid.h>
#include <tqcombobox.h>

// KDE includes
#include <tdelocale.h>
#include <kdebug.h>
#include <tdestandarddirs.h>
#include <tdelocale.h>
#include <tdeio/netaccess.h>
#include <tdeio/job.h>
#include <ktrader.h>
#include <klibloader.h>
#include <tdelistview.h>
#include <tdelistbox.h>
#include <knuminput.h>
#include <kpushbutton.h>
#include <tdemessagebox.h>
#include <tdetempfile.h>
#include <kcombobox.h>

// Project includes
#include "kmflistviewitem.h"
#include "../version.h"
#include "../core/kmfgenericdoc.h"
#include "../core/kmfnetwork.h"
#include "../core/kmfprotocol.h"
#include "../core/kmfprotocollibrary.h"
#include "../core/kmfprotocolcategory.h"
#include "../core/kmferror.h"
#include "../core/kmferrorhandler.h"

namespace KMF {
KMFGenericInterfaceEditProtocol::KMFGenericInterfaceEditProtocol( TQWidget *parent, const char *name, WFlags f )
		: KMyFirewallGenericInterfaceEditProtocolWidget( parent, name, f ) {
	// m_protocolsLoaded = false;
//	m_protocols.clear();
		
	connect( m_lv_protocols, TQ_SIGNAL( pressed( TQListViewItem* ) ) ,
		this, TQ_SLOT( slotNewItemSelected( TQListViewItem* ) ) );
	
	connect( m_lb_tcpPorts, TQ_SIGNAL( currentChanged ( TQListBoxItem * ) ), this, TQ_SLOT( slotCurrentTCPPortChanged( TQListBoxItem * ) ) );
	
	connect( m_lb_udpPorts, TQ_SIGNAL( currentChanged ( TQListBoxItem * ) ), this, TQ_SLOT( slotCurrentUDPPortChanged( TQListBoxItem * ) ) );
	
	// connect( m_sb_port_num, TQ_SIGNAL( valueChanged( int ) ), this, TQ_SLOT( slotPortVauleChanged( int ) ) );
	
	connect( m_te_desc, TQ_SIGNAL( textChanged() ), this, TQ_SLOT( slotNameDescritionChanged() ) );
	connect( m_le_protocolName , TQ_SIGNAL( textChanged( const TQString& ) ), this, TQ_SLOT( slotNameDescritionChanged() ) );
	connect( m_rb_tcp, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotProtocolTypeChanged() ) );
	connect( m_rb_udp, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotProtocolTypeChanged() ) );
	
	connect( m_b_add_port, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotAddPort() ) );
	connect( m_b_del_port, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotDelPort() ) );
	
	connect( m_b_new_protocol, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotAddProtocol() ) );
	connect( m_b_del_protocol, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotDelProtocol() ) );
	
	connect( m_cb_showAll,TQ_SIGNAL( toggled( bool ) ), this , TQ_SLOT( slotUpdateView() ) );
}


KMFGenericInterfaceEditProtocol::~KMFGenericInterfaceEditProtocol() {}



void KMFGenericInterfaceEditProtocol::slotNewItemSelected( TQListViewItem* qit ) {
	kdDebug() << "void KMFGenericInterfaceEditProtocol::slotNewItemSelected(...)" << endl;
	
	KMFListViewItem *item = dynamic_cast<KMFListViewItem*> ( qit ); 
	if ( ! item ) {
		kdDebug() << "Item was no KMFListViewItem!" << endl;
		m_gb_edit->setEnabled( false );
		m_b_del_protocol->setEnabled( false );
		return;
	}
	
	if ( m_protocol && 
			item->type() == NetfilterObject::PROTOCOL && 
			m_protocol->uuid() == item->protocol()->uuid() ) {
		kdDebug() << "Selected Same Protocal again" << endl;
		m_gb_edit->setEnabled( m_protocol->customProtocol() );
		m_b_del_protocol->setEnabled( m_protocol->customProtocol() );
		return;
	}
	if ( item->type() != NetfilterObject::PROTOCOL ) {
		return;
	} 
	m_gb_edit->setEnabled( true );
	m_b_del_protocol->setEnabled( true );
	m_protocol = item->protocol();
	updateEdit();
}

void  KMFGenericInterfaceEditProtocol::slotCurrentTCPPortChanged( TQListBoxItem * item ) {
	kdDebug() << "void KMFGenericInterfaceEditProtocol::slotCurrentTCPPortChanged()" << endl;
	if ( ! item ) {
		return;
	}

	m_lb_udpPorts->clearSelection();
// 	m_sb_port_num->setValue( item->text().toInt() );
	m_rb_tcp->setChecked( true );
	
}

void  KMFGenericInterfaceEditProtocol::slotCurrentUDPPortChanged( TQListBoxItem * item ) {
	kdDebug() << "void KMFGenericInterfaceEditProtocol::slotCurrentUDPPortChanged()" << endl;
	if ( ! item ) {
		return;
	}
	m_lb_tcpPorts->clearSelection();
/*	m_sb_port_num->blockSignals( true );
	m_sb_port_num->setValue( item->text().toInt() );
	m_sb_port_num->blockSignals( false );*/
	m_rb_udp->setChecked( true );
}

void KMFGenericInterfaceEditProtocol::slotProtocolTypeChanged() {
	kdDebug() << "void KMFGenericInterfaceEditProtocol::slotProtocolTypeChanged()" << endl;
	if ( ! m_protocol ) {
		kdDebug() << "\n\nWARNING: No Protocol Object to save Changes in  Memory!!\n\n" << endl;
		return;
	}
	
	m_lb_udpPorts->clearSelection();
	m_lb_tcpPorts->clearSelection();
}
void KMFGenericInterfaceEditProtocol::slotAddPort() {
	kdDebug() << "void KMFGenericInterfaceEditProtocol::slotAddPort()" << endl;
	if ( ! m_protocol ) {
		kdDebug() << "\n\nWARNING: No Protocol Object to save Changes in  Memory!!\n\n" << endl;
		return;
	}
	
	m_lb_udpPorts->clearSelection();
	m_lb_tcpPorts->clearSelection();
	if ( m_rb_tcp->isChecked() ) {
		m_protocol->addPort( m_sb_port_num->text(), KMFProtocol::TCP );
		m_lb_tcpPorts->blockSignals( true );
		m_lb_tcpPorts->clear();
		// TQStringList l = TQStringList::split( ",", m_protocol->tcpPortsList() );
		m_lb_tcpPorts->insertStringList( TQStringList::split( ",", m_protocol->tcpPortsList() ) );
		
	
		m_lb_tcpPorts->blockSignals( false );
		
		for( uint i= 0; i< m_lb_tcpPorts->count(); i++ ) {
			if ( m_lb_tcpPorts->text( i ) == m_sb_port_num->text() ) {
				m_lb_tcpPorts->setSelected( i, true );
			}
		}
		slotProtocolChanged();
	} else if ( m_rb_udp->isChecked() ) {
		m_protocol->addPort( m_sb_port_num->text(), KMFProtocol::UDP );
		m_lb_udpPorts->blockSignals( true );
		m_lb_udpPorts->clear();
// 		for( uint i= 0; i< m_protocol->udpPorts()->count(); i++ ) {
// 			m_lb_udpPorts->insert( *m_protocol->udpPorts().at( i ) );
// 		}
		m_lb_udpPorts->insertStringList( TQStringList::split( ",", m_protocol->udpPortsList() ) );
		m_lb_udpPorts->blockSignals( false );
				
		for( uint i= 0; i< m_lb_udpPorts->count(); i++ ) {
			if ( m_lb_udpPorts->text( i ) == m_sb_port_num->text() ) {
				m_lb_udpPorts->setSelected( i, true );
			}
		}
		slotProtocolChanged();
	}
}

void KMFGenericInterfaceEditProtocol::slotDelPort() {
	kdDebug() << "void KMFGenericInterfaceEditProtocol::slotDelPort()" << endl;
	if ( m_lb_tcpPorts->selectedItem() ) {
		m_protocol->delPort( m_lb_tcpPorts->selectedItem()->text(), KMFProtocol::TCP );
		m_lb_tcpPorts->blockSignals( true );
		m_lb_tcpPorts->clear();
		m_lb_tcpPorts->insertStringList( TQStringList::split( ",", m_protocol->tcpPortsList() ) );
		m_lb_tcpPorts->blockSignals( false );
		if ( m_lb_tcpPorts->count() > 0 ) {
			m_lb_tcpPorts->setSelected( 0, true );
		}
		slotProtocolChanged();
	} else if ( m_lb_udpPorts->selectedItem() ) {
		m_protocol->delPort( m_lb_udpPorts->selectedItem()->text(), KMFProtocol::UDP );
		m_lb_udpPorts->blockSignals( true );
		m_lb_udpPorts->clear();
		m_lb_udpPorts->insertStringList( TQStringList::split( ",", m_protocol->udpPortsList() ) );
		m_lb_udpPorts->blockSignals( false );
		if ( m_lb_udpPorts->count() > 0 ) {
			m_lb_udpPorts->setSelected( 0, true );
		}
		slotProtocolChanged();
	}
}

void KMFGenericInterfaceEditProtocol::slotAddProtocol() {
	kdDebug() << "void KMFGenericInterfaceEditProtocol::slotAddProtocol()" << endl;
// 	KMFProtocolCategory* catCustom = KMFProtocol::findCategory( KMFProtocolCategory::customCategoryUuid() );
// 	if ( ! catCustom ) {
// 		catCustom = KMFProtocolCategory::createCategory( i18n("Custom Protocols") );
// 		catCustom->setUuid( KMFProtocolCategory::customCategoryUuid().toString() );
// 	}
	
	KMFProtocol *p = KMFProtocolCategory::getCustomCategory()->createProtocol( i18n("New Protocol") );
	p->setName( i18n("New Protocol") );
	p->setCustomProtocol( true );
	m_protocol	= p;
	slotUpdateView();

// 	KMFListViewItem *item = new KMFListViewItem( m_lv_protocols, p );
// 	item->loadNetfilterObject( p );
// 	item->setupProtocolView();
// 	
// 	m_lv_protocols->setSelected( item, true );
// 	slotNewItemSelected( item );
}

void KMFGenericInterfaceEditProtocol::slotDelProtocol() {
	kdDebug() << "void KMFGenericInterfaceEditProtocol::slotDelProtocol()" << endl;
	if ( ! m_protocol ) {
		return;
		kdDebug() << "\n\nWARNING: No Protocol Object to save Changes in  Memory!!\n\n" << endl;
	}
	int doit = 	KMessageBox::questionYesNo ( this , i18n( "<p>Are you sure that you want to delete "
		                                        "the protocol: <b>%1</b>?</p>").arg( m_protocol->name() ),
		                                        i18n( "Delete Protocol" ), KStdGuiItem::yes(), KStdGuiItem::no() /*, "protocol_edit_delete_protocol"*/ );
		                                         
	// kdDebug() << "Got Answer: " << doit << endl;		                                         
	if ( doit != 3 ) {	
		return;
	}
	// FIXME: Casees Mem0ry Leak, but app crashed othwise!
	m_protocol->category()->delProtocol( m_protocol, false );
	m_protocol = 0; 
	slotNewItemSelected( 0 );
	slotUpdateView();
}

void KMFGenericInterfaceEditProtocol::slotOnProtocolDeleleted( TQObject* ) {
	m_protocol = 0;
	slotUpdateView();
	slotNewItemSelected( 0 );
}

void KMFGenericInterfaceEditProtocol::slotPortVauleChanged( int val ) {
	kdDebug() << "void KMFGenericInterfaceEditProtocol::slotPortVauleChanged()" << endl;
	if ( ! m_protocol ) {
		kdDebug() << "\n\nWARNING: No Protocol Object to save Changes in  Memory!!\n\n" << endl;
		return;
	}
	
	TQString s = "";
	s.setNum( val );
	if ( m_rb_udp->isChecked() ) {
		TQListBoxItem *i = m_lb_udpPorts->selectedItem();
		if ( ! i ) {
			return;
		}
		TQString strVal = "";
		strVal.setNum( val );
		if ( m_protocol->replaceUDPPort( i->text().toInt(), val ) ) {
			m_lb_udpPorts->blockSignals( true );
			m_lb_udpPorts->clear();
			m_lb_udpPorts->insertStringList( TQStringList::split( ",", m_protocol->udpPortsList() ) );
			
			for( uint i= 0; i< m_lb_udpPorts->count(); i++ ) {
				if ( m_lb_udpPorts->text( i ) == strVal ) {
					m_lb_udpPorts->setSelected( i, true );
					break;
				}
			}
			m_lb_udpPorts->blockSignals( false );
			slotProtocolChanged();
		}
	} else if ( m_rb_tcp->isChecked() ) {
		TQListBoxItem *i = m_lb_tcpPorts->selectedItem();
		if ( ! i ) {
			return;
		}
		
		TQString strVal = "";
		strVal.setNum( val );
		
		if( m_protocol->replaceTCPPort( i->text().toInt(), val ) ) {
			m_lb_tcpPorts->blockSignals( true );
			m_lb_tcpPorts->clear();
			m_lb_tcpPorts->insertStringList( TQStringList::split( ",", m_protocol->tcpPortsList() ) );
			for( uint i= 0; i< m_lb_tcpPorts->count(); i++ ) {
				if ( m_lb_tcpPorts->text( i ) == strVal ) {
					m_lb_tcpPorts->setSelected( i, true );
					break;
				}
			}
			m_lb_tcpPorts->blockSignals( false );
			slotProtocolChanged();
		}
	}
}

void KMFGenericInterfaceEditProtocol::slotNameDescritionChanged() {
	kdDebug() << "void KMFGenericInterfaceEditProtocol::slotNameDescritionChanged()" << endl;
	if ( ! m_protocol ) {
		kdDebug() << "\n\nWARNING: No Protocol Object to save Changes in  Memory!!\n\n" << endl;
		return;
	}
	
	if (  ! m_le_protocolName->text().isEmpty() ) {
		m_protocol->setName( m_le_protocolName->text().stripWhiteSpace().simplifyWhiteSpace() );
	}
	m_protocol->setDescription( m_te_desc->text().stripWhiteSpace().simplifyWhiteSpace() );
	
	// m_protocol->setCategory( m_cob_
	slotProtocolChanged();
}

void KMFGenericInterfaceEditProtocol::slotProtocolChanged() {
	kdDebug() << "void KMFGenericInterfaceEditProtocol::slotProtocolChanged()" << endl;
	TQListViewItemIterator it( m_lv_protocols );
    while ( it.current() ) {
        KMFListViewItem *kit = dynamic_cast<KMFListViewItem*> ( it.current() );
		if ( 	kit->type() == NetfilterObject::PROTOCOL && 
				kit->protocol()->uuid() == m_protocol->uuid() ) {
			kit->setupProtocolView();
			kit->setOpen( true );
			return;
		}
        ++it;
    }
}

void KMFGenericInterfaceEditProtocol::updateEdit() {
	kdDebug() << "void KMFGenericInterfaceEditProtocol::updateEdit()" << endl;
	if ( ! m_protocol ) {
		kdDebug() << "\n\nWARNING: No Protocol Object to save Changes in  Memory!!\n\n" << endl;
		m_gb_edit->setEnabled( false );
		m_b_del_protocol->setEnabled( false );
		return;
	}
	m_gb_edit->setEnabled( m_protocol->customProtocol() );
	m_b_del_protocol->setEnabled( m_protocol->customProtocol() );
	
	m_le_protocolName->blockSignals( true );
	m_te_desc->blockSignals( true );
	
	m_le_protocolName->setText( m_protocol->name() );
	m_te_desc->setText( m_protocol->description() );
	
	m_le_protocolName->blockSignals( false );
	m_te_desc->blockSignals( false );
	
	m_lb_tcpPorts->clear();
	m_lb_udpPorts->clear();
	m_lb_tcpPorts->insertStringList(  TQStringList::split( ",", m_protocol->tcpPortsList() ) );
	m_lb_udpPorts->insertStringList(  TQStringList::split( ",", m_protocol->udpPortsList() ) );
}

void KMFGenericInterfaceEditProtocol::slotUpdateView() {
	kdDebug() << "void KMFGenericInterfaceEditProtocol::slotUpdateView()" << endl;
	m_lv_protocols->clear();
	KMFProtocolCategory::getCustomCategory();
	
	if ( m_cb_showAll->isChecked() ) {
		TQValueList<KMFProtocolCategory*>& protCats =  KMFProtocolLibrary::instance()->protocolCategories();
		TQValueList<KMFProtocolCategory*>::iterator it;
		for( it = protCats.begin(); it != protCats.end(); ++it ) {
			KMFProtocolCategory* cat = *it;
			kdDebug() << "\nSetup Category: Item" << cat->name() << endl;
			
			KMFListViewItem *item = new KMFListViewItem( m_lv_protocols, cat );
			item->loadNetfilterObject( cat );
			item->setupProtocolCategoryView();
			if ( cat == KMFProtocolCategory::getCustomCategory() ) {
				item->setOpen( true );
			}
		}
	} else {
		KMFProtocolCategory* customCat = KMFProtocolCategory::getCustomCategory();
		KMFListViewItem *item = new KMFListViewItem( m_lv_protocols, customCat );
		item->loadNetfilterObject( customCat );
		item->setupProtocolCategoryView();
		item->setOpen( true );
	}
	
	TQValueList< KMFProtocol* >& prots = KMFProtocolCategory::getCustomCategory()->protocols();
	TQValueList< KMFProtocol* >::iterator it;
	for( it = prots.begin(); it != prots.end(); ++it ) {
		KMFProtocol* p= *it;
		disconnect( p, TQ_SIGNAL( destroyed( TQObject* ) ),
			this, TQ_SLOT( slotOnProtocolDeleleted( TQObject* ) ) );
		connect( p, TQ_SIGNAL( destroyed( TQObject* ) ),
			this, TQ_SLOT( slotOnProtocolDeleleted( TQObject* ) ) );
	}
	
	setEnabled( true );
}


void KMFGenericInterfaceEditProtocol::loadDoc( KMFNetwork* doc  ) {
	kdDebug() << "void KMFGenericInterfaceLogging::loadDoc( KMFGenericDoc* )" << endl;
	m_network = doc;
	slotUpdateView();
}

void KMFGenericInterfaceEditProtocol::saveProtocols() {
	kdDebug() << "KMFGenericInterfaceEditProtocol::saveProtocols()" << endl;
	KMFErrorHandler *errH = new KMFErrorHandler( "KMFErrorHandler" );
	errH->showError( KMFProtocolLibrary::instance()->saveProtocolLibrary() );
}

}

#include "kmfgenericinterfaceeditprotocol.moc"
