/***************************************************************************
   begin                : Thu Apr 24 2003
   copyright            : (C) 2003 by Christian Hubinger
   email                : chubinger@irrsinnig.org
***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "netfilterobject.h"

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

// project includes
#include "kmfdoc.h"
#include "kmftarget.h"
#include "kmfnethost.h"
#include "kmfnetzone.h"
#include "kmfprotocol.h"
#include "iptrule.h"
#include "iptable.h"
#include "iptchain.h"
#include "iptruleoption.h"
#include "kmfundoengine.h"
#include "xmlnames.h"

namespace KMF {

//########### static stuff
TQMap<TQUuid, NetfilterObject*>* NetfilterObject::m_uuid_dict = new TQMap<TQUuid, NetfilterObject*>;

NetfilterObject* NetfilterObject::findObject( const TQUuid& uuid ) {
	TQMap<TQUuid, NetfilterObject*>::iterator it = getUuidObjectDict()->find( uuid );
	if ( it != getUuidObjectDict()->end() ) {
		return (*it);
	}
	return 0;
}

int NetfilterObject::objectCount( int type ) {
	if ( type == -1 ) {
		return m_uuid_dict->count();
	}
	
	int count = 0;
	TQMap<TQUuid, NetfilterObject*>::Iterator it;
	for ( it = m_uuid_dict->begin(); it != m_uuid_dict->end(); ++it ) {
		if ( it.data() && it.data()->type() == type ) {
			count++;
		}
	}
	return count;
}


//########### end static stuff

NetfilterObject::NetfilterObject( NetfilterObject *parent, const char* name ) : TQObject( parent, name ) {
	// kdDebug() << "NetfilterObject::( NetfilterObject *parent " << name << " )" << endl;
	m_uuid = TQUuid::createUuid();
	m_parent = parent;
	m_name = i18n( "Untitled" );
	m_desc = i18n( "No Description Available" );
	m_uuid_dict->insert( uuid(), this, true );
	// kdDebug() << "Created NetfilterObject: " << uuid() << endl;
}

NetfilterObject::~NetfilterObject() {
	m_uuid_dict->remove( m_uuid );
	if ( m_uuid_dict->contains( m_uuid ) ) {
		kdDebug() << "Could not delete object from NetfilterObject::m_uuid_dict" << endl;

	}
}

void NetfilterObject::setUuid( const TQUuid& newUuid ) {
	if ( newUuid.isNull() ) {
		return;
	}
	
	TQUuid toSetUuid = newUuid;
	
	while ( m_uuid != toSetUuid &&  m_uuid_dict->contains( toSetUuid ) ) {
		kdDebug() << "NetfilterObject::setUuid( " << toSetUuid << ") new uuid allready in use! Generating new!" << endl;
		toSetUuid = TQUuid::createUuid();
	}
	
	m_uuid_dict->remove( m_uuid );
	if ( m_uuid_dict->contains( m_uuid ) ) {
		kdDebug() << "Could not delete object from NetfilterObject::m_uuid_dict" << endl;
	}
	
//	kdDebug() << "NetfilterObject: " << uuid() << "->setUuid " << toSetUuid << endl;
	m_uuid = toSetUuid;
	
	m_uuid_dict->insert( m_uuid, this, true );
}

void NetfilterObject::setParent( NetfilterObject *parent ) {
	if ( ! parent || parent == m_parent ) {
		return;
	}
	m_parent = parent;
	changed();
}

bool NetfilterObject::isChildOf( const TQUuid& id ) {
	if ( ! m_parent ) {
		// kdDebug() << "NetfilterObject: " << name() << ":" << uuid() << " ->isChildOf( " << id << " ) - No More Parent return: false" << endl;
		return false;
	}
	if ( m_parent->uuid() == id ) {
		// kdDebug() << "NetfilterObject: " << name() << ":" << uuid() << " ->isChildOf( " << id << " ) - Parent Matched return: true" << endl;
		return true;
	}
	return m_parent->isChildOf( id );
}

int NetfilterObject::getLevel() {
	// kdDebug() << "NetfilterObject::getLevel()" << endl;
	int lev = 0;
	getLevel( lev );
	return lev;
}

void NetfilterObject::getLevel( int& currlevel ) {
	// kdDebug() << "NetfilterObject::getLevel( int *currlevel )" << endl;
	if ( m_parent ) {
		currlevel++;
		m_parent->getLevel( currlevel );
	}
}

const TQString& NetfilterObject::name() {
	// kdDebug() << "const TQString& NetfilterObject::name()" << endl;
	return m_name;
}


void NetfilterObject::setName( const TQString& name ) {
	//kdDebug() << "const TQString& NetfilterObject::setName( const TQString& " << name << " )" << endl;
	if ( name.isNull() || name == m_name ) {
		return;
	}
	m_name = name;
	changed();
}

const TQString& NetfilterObject::description() {
	return m_desc;
}

void NetfilterObject::setDescription( const TQString& desc ) {
	if ( desc.isNull() ) {
		return;
	}
	if ( desc == m_desc ) {
		return;
	}
	m_desc = desc;
	changed();
}

const TQString& NetfilterObject::getXMLSniplet() {
// 	kdDebug() << "const TQString& NetfilterObject::getXMLsniplet()" << endl;
	TQDomDocument tmp_doc = getDOMTree();
	const TQString& xml = tmp_doc.toString();
	// 	kdDebug() << "Creted XML:\n" << xml << "\n" << endl;
	return *( new TQString( xml ) );
}

void NetfilterObject::loadUuid( TQDomNode& node, TQStringList& errors ) {
	if ( ! node.toElement().hasAttribute( XML::Uuid_Attribute ) ) {
		errors.append( KMFError::getAsString( KMFError::WARNING, i18n( "No uuid saved in node %1" ).arg( node.nodeName () ) ) );
		return;
	}
// 	if ( KMFUndoEngine::instance()->preserveObjectUuid() ) {
		const TQString& newUuid = node.toElement().attribute( XML::Uuid_Attribute );
		if ( newUuid.isEmpty() ) {
			errors.append( KMFError::getAsString( KMFError::WARNING, i18n( "No uuid saved in node %1" ).arg( node.nodeName () ) ) );
			return;
		}
		// KMFUndoEngine::instance()->log( i18n( "Overwrite my uuid: %1 with %2" ).arg( uuid().toString() ).arg( newUuid ), KMFError::OK, this );
		setUuid( newUuid );
// 	}
	
}
void NetfilterObject::saveUuid( TQDomNode& node ) {
	node.toElement().setAttribute( XML::Uuid_Attribute, uuid().toString() );
}

void NetfilterObject::changed() {
	// kdDebug() << "void NetfilterObject::changed() : m_object_id " << uuid() << endl;
	KMFUndoEngine::instance()->changed( uuid() );
}

}
