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

// TQt includes
#include <tqdom.h>

// KDE includes
#include <kdebug.h>
#include <tdelocale.h>

// Project includes
#include "kmfundoengine.h"
#include "kmfprotocol.h"
#include "kmfprotocollibrary.h"
#include "xmlnames.h"

namespace KMF {

/* Never Ever Change This Uuids! */
const TQUuid& KMFProtocolCategory::customCategoryUuid() {
	return *(new TQUuid( "{9758012f-e2a0-4594-938f-c154a7078752}" ) );
};
const TQUuid& KMFProtocolCategory::miscCategoryUuid() {
	return *(new TQUuid( "{02e7113c-535d-447d-8a25-5c9e89fd3f79}" ) );
};	


KMFProtocolCategory* KMFProtocolCategory::createCategory( const TQString& name ) {
	KMFProtocolCategory* cat = new KMFProtocolCategory( 0, name.latin1() );
	cat->setName( name );
	return cat;
}

KMFProtocol* KMFProtocolCategory::createProtocol( const TQString& name ) {
	KMFProtocol* prot = new KMFProtocol( this, name.latin1() );
	addProtocol( prot );
	return prot;
}

KMFProtocolCategory* KMFProtocolCategory::getCustomCategory() {
	KMFProtocolCategory* catCustom = KMFProtocolLibrary::instance()->findCategory( KMFProtocolCategory::customCategoryUuid() );
	if ( ! catCustom ) {
		catCustom = KMFProtocolCategory::createCategory( i18n("Custom Protocols") );
		catCustom->setUuid( KMFProtocolCategory::customCategoryUuid().toString() );
	}
	return catCustom;
}



KMFProtocolCategory::KMFProtocolCategory ( NetfilterObject* parent, const char* name ) : NetfilterObject ( parent, name ) {
	// m_protocols;
}

KMFProtocolCategory::~KMFProtocolCategory() {}

int KMFProtocolCategory::type() {
	return NetfilterObject::PROTOCOLCATEGORY;
}

void KMFProtocolCategory::clear() {
}


TQValueList<KMFProtocol*>& KMFProtocolCategory::protocols() const {
	TQValueList<KMFProtocol*>* ret_val = new TQValueList<KMFProtocol*>;
	*ret_val = m_protocols;
	return *ret_val;
}


KMFProtocol* KMFProtocolCategory::findProtocolByName ( const TQString& name ) const {
	// kdDebug() << "KMFProtocol* KMFProtocolCategory::findProtocolByName( const TQString& name ) const" << endl;
	TQValueList< KMFProtocol* >::const_iterator it;
	for ( it = m_protocols.constBegin(); it != m_protocols.constEnd(); ++it ) {
		KMFProtocol *p = *it;
		if ( p->name() == name ) {
			return p;
		}
	}
	return 0;
}
KMFProtocol* KMFProtocolCategory::findProtocolByUuid ( const TQUuid& uuid ) const {
//	kdDebug() << "KMFProtocol* KMFProtocolCategory::findProtocolByUuid( const TQUuid& uuid ) const" << endl;
	TQValueList< KMFProtocol* >::const_iterator it;
	for ( it = m_protocols.constBegin(); it != m_protocols.constEnd(); ++it ) {
		KMFProtocol *p = *it;
		if ( p->uuid() == uuid ) {
			return p;
		}
	}
	return 0;
}

KMFProtocol* KMFProtocolCategory::addProtocol ( KMFProtocol* proto ) {
	// kdDebug() << "KMFProtocol* KMFProtocolCategory::addProtocol( KMFProtocol* " << proto->name() << " )" << endl;
	// proto->category()->delProtocol( proto );
	m_protocols.append ( proto );
	proto->setCategory( this );
	return proto;
}

void KMFProtocolCategory::delProtocol ( KMFProtocol* prot, bool destructive = false ) {
//  kdDebug() << "void KMFProtocolCategory::delProtocol( KMFProtocol* prot )" << endl;
	TQValueList<KMFProtocol*>::iterator it;
	for ( it = m_protocols.begin(); it != m_protocols.end(); ++it ) {
		KMFProtocol *p = *it;
		if ( p->name() == prot->name() ) {
			kdDebug() << "Delete protocol: " << prot->name() << " from category:  " << name() << endl;
			m_protocols.remove( p );
			if ( destructive ) {
				p->deleteLater();
			}
			
			changed();
			return;
			
		}
	}
	changed();
}

void KMFProtocolCategory::slotOnProtocolDeleted( TQObject* prot ) {
	kdDebug() << "KMFProtocolCategory::slotOnProtocolDeleted( TQObject* )" << endl;
	TQValueList<KMFProtocol*>::iterator it;
	for ( it = m_protocols.begin(); it != m_protocols.end(); ++it ) {
		KMFProtocol *p = *it;
		if ( p == prot ) {
			kdDebug() << "Delete protocol from category:  " << name() << endl;
			m_protocols.remove( p );
			changed();
			return;
		}
	}
	// deleteLater();
}

const TQDomDocument& KMFProtocolCategory::getDOMTree() {
	kdDebug() << "const TQDomDocument& KMFProtocolCategory::getDOMTree() " << endl;
	TQDomDocument doc;
	TQDomElement root = doc.createElement ( XML::ProtocolCategory_Element );
	NetfilterObject::saveUuid ( root );

	root.setAttribute (  XML::Name_Attribute, name() );
	root.setAttribute ( XML::Description_Attribute, description() );

	TQValueList< KMFProtocol* >::iterator it;
	for ( it = m_protocols.begin(); it != m_protocols.end(); ++it ) {
		KMFProtocol* p = *it;
		if ( p->customProtocol() ) {
			root.appendChild ( (*it)->getDOMTree( ) );
		}
	}
	doc.appendChild ( root );
	return * ( new TQDomDocument ( doc ) );
}

void KMFProtocolCategory::loadXML ( const TQDomDocument& doc, TQStringList& errors ) {
	// kdDebug() << "void KMFProtocolCategory::loadXML( const TQDomDocument& )" << endl;
	TQDomElement root = doc.documentElement();
	loadXML ( root, errors );
}

void KMFProtocolCategory::loadXML ( TQDomNode root, TQStringList& errors ) {
//	kdDebug() << "void KMFProtocolCategory::loadXML( TQDomNode root )" << endl;
	NetfilterObject::loadUuid ( root, errors );
	
	setName( root.toElement().attribute ( XML::Name_Attribute ) );
	setDescription( root.toElement().attribute ( XML::Description_Attribute ) );

	TQValueList< KMFProtocol* > xmlDefinedProtocols;
	TQDomNode curr = root.firstChild();
	while ( !curr.isNull() ) {
		if ( curr.isElement() && ( curr.nodeName() == XML::Protocol_Element ) ) {
			TQString name = curr.toElement().attribute (  XML::Name_Attribute );
			TQString uuid = curr.toElement().attribute (  XML::Uuid_Attribute );
			KMFProtocol *p = findProtocolByUuid( uuid );
			if ( ! p ) {
				p = createProtocol( name );
				kdDebug() << " + + Register Protocol: " << name << " with uuid: " << uuid << endl;
				TQDomDocument protocol;
				protocol.appendChild( curr.cloneNode( true ) );
				TQStringList *errors = new TQStringList();
				p->loadXML( protocol, *errors );
			}
			xmlDefinedProtocols.append ( p );
		}
// 		if ( curr.isElement() && ( curr.nodeName() == XML::ProtocolUsage_Element ) ) {
// 			TQString uuid = curr.toElement().attribute ( XML::ProtocolUuid_Attribute );
// 			KMFProtocol *p = findProtocolByUuid( uuid );
// 			if ( ! p ) {
// 				p = createProtocol( curr.toElement().attribute ( XML::Name_Attribute ) );
// 				TQDomDocument protocol;
// 				protocol.appendChild( curr.cloneNode( true ) );
// 				TQStringList *errors = new TQStringList();
// 				p->loadXML( protocol, *errors );
// 			}
// 			xmlDefinedProtocols.append ( p );
// 		}
		curr = curr.nextSibling();
	}

// 	{
// 		TQValueList< KMFProtocol* >& allprotocols = protocols();
// 		TQValueList< KMFProtocol* >::iterator itAllProtocols;
// 		for ( itAllProtocols = allprotocols.begin(); itAllProtocols != allprotocols.end(); ++itAllProtocols ) {
// 			KMFProtocol *oldProtocol = *itAllProtocols;
// 
// 			bool found = false;
// 			TQValueList< KMFProtocol* >::iterator itProtocols;
// 			for ( itProtocols = xmlDefinedProtocols.begin(); itProtocols != xmlDefinedProtocols.end() && ! found; ++itProtocols ) {
// 				KMFProtocol* p = *itProtocols;
// 				if ( p == oldProtocol ) {
// 					found = true;
// 				}
// 			}
// 
// 			if ( ! found ) {
// 				KMFUndoEngine::instance()->log ( i18n ( "Removing unused protocol: %1" ).arg ( oldProtocol->name() ), KMFError::OK, this );
// 				delProtocol ( oldProtocol );
// 			}
// 		}
// 	}
	changed();
}

}

#include "kmfprotocolcategory.moc"
