//
// C++ Implementation: kmfnethost
//
// Description:
//
//
// Author: Christian Hubinger <chubinger@gmail.com>, (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 "kmfnethost.h"

// QT includes
#include <qdom.h>

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

// Project includes
#include "kmfcheckinput.h"
#include "kmfprotocol.h"
#include "kmfnetzone.h"
#include "kmfgenericdoc.h"
#include "kmferror.h"
#include "ipaddress.h"

KMFNetHost::KMFNetHost( QObject *parent, const QString& name ) : NetfilterObject( parent ){
	m_zone = 0;
	m_logIncoming = false;
	m_logOutgoing = false;
	m_guiName = i18n("New Host");
	m_address = new IPAddress( 0,0,0,0 );
	m_limitScale = "minute";
	m_limitNum = -1;
	m_protocols.setAutoDelete( true );
	setName( name );
	m_object_type = NETHOST;
	if ( KMFNetZone* zone = dynamic_cast<KMFNetZone*> ( parent ) ) {
		m_zone = zone;
		m_address->setAddress( m_zone->address()->toString() );
	} else {
		kdDebug() << "ERROR: KMFNetHost called with wrong Parent class." << endl;
	}
}
KMFNetHost::~KMFNetHost() {
	kdDebug() << "KMFNetHost::~KMFNetHost()" << endl;
	m_protocols.clear();
	delete m_address;
}

void KMFNetHost::setGuiName( const QString& name){
	if ( !name.isNull() && !name.isEmpty() )
		m_guiName = name;
}

void KMFNetHost::setAddress( const QString& addr ) {
	m_address->setAddress( addr );
	changed();
}

void KMFNetHost::setParentZone( KMFNetZone* zone ){
	m_zone = zone;
}

void KMFNetHost::setLogIncoming( bool onoff ) {
	m_logIncoming = onoff;
}

void KMFNetHost::setLogOutgoing( bool onoff ) {
	m_logOutgoing = onoff;
}

void KMFNetHost::setLimit( int num, const QString& scale ) {
	if ( num < 1 ) {
		m_limitNum = -1;
		m_limitScale = "minute";
		return;
	}
	m_limitNum = num;
	m_limitScale = scale;
}

bool KMFNetHost::limit() const {
	if ( m_limitNum > 0 )
		return true;
	
	return false;
}

int KMFNetHost::limitRate() const {
	return m_limitNum;
}

const QString& KMFNetHost::limitScale() const {
	return m_limitScale;
}

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

KMFProtocol* KMFNetHost::findProtocol( const QString& name ) const {
// 	kdDebug() << "KMFProtocol* KMFNetHost::findProtocol( const QString& name ) const" << endl;
	QPtrListIterator<KMFProtocol> it(m_protocols);
	while ( it.current() ) {
		KMFProtocol *p = it.current();
		++it;
		if ( p->name() == name ) {
// 			kdDebug() << "Found Protocol: "  << name << endl;
			return p;
		}
	}
	return 0;
}

KMFProtocol* KMFNetHost::addProtocol( const QString& name, const QDomDocument& xml ) {
// 		kdDebug() << "KMFNetHost* KMFNetZone::addProtocol( const QString& name, const QDomDocument& xml )" << endl;
	QPtrListIterator<KMFProtocol> it( m_protocols );
	while ( it.current() ) {
		KMFProtocol *p =  it.current();
		++it;
		kdDebug() << "KMFNetHost::addProtocol: Compare Protocol: " << p->name() << " with Protocol: " << name << endl;
		if ( p->name() == name ) {
			kdDebug() << "WARNING: Ignoreing duplicate protocol entry in zone" << endl;
			return 0;
		}
	}
	KMFProtocol* new_protocol = new KMFProtocol( this );
	new_protocol->loadXML( xml );
	m_protocols.append( new_protocol );
	return new_protocol;
}
KMFProtocol* KMFNetHost::addProtocol( const QString& name ) {
// 		kdDebug() << "KMFNetHost* KMFNetZone::addProtocol( const QString& name, const QDomDocument& xml )" << endl;
	QPtrListIterator<KMFProtocol> it( m_protocols );
	while ( it.current() ) {
		KMFProtocol *p =  it.current();
		++it;
		if ( p->name() == name ) {
 			kdDebug() << "WARNING: Ignoreing duplicate protocol entry in zone" << endl;
			return 0;
		}
	}
	KMFProtocol* new_protocol = new KMFProtocol( this );
	m_protocols.append( new_protocol );
	return new_protocol;
}

void KMFNetHost::delProtocol( KMFProtocol* prot ){
// 	kdDebug() << "void KMFNetHost::delProtocol( KMFProtocol* prot )" << endl;
	QPtrListIterator<KMFProtocol> it( m_protocols );
	bool deleted = false;
	while ( it.current() ) {
		KMFProtocol *p =  it.current();
		kdDebug() << "Comparing protocol: " << prot->name() << " with protocol: " << p->name() << endl;
		if ( p->name() == prot->name() ) {
			kdDebug() << "Delete protocol: " << prot->name() << " from host:  " << m_name << endl;
			m_protocols.remove( p );
			deleted = true;
		}
		++it;
	}
	
	if ( ! deleted ) {
		kdDebug() << "WARNING: Couldn't delete protocol: " << prot->name() << " from host:  " << m_name << endl;
	}
}

bool KMFNetHost::protocolInherited( const QString& name ) const {
//  	kdDebug() << "bool KMFNetHost::protocolInherited() const" << endl;
	if ( ! m_zone )
		return false;
	QPtrListIterator<KMFProtocol> it( m_zone->protocols() );
	while ( it.current() ) {
		KMFProtocol *p = it.current();
		++it;
		if ( p->name() == name ) {
// 			kdDebug() << "Found Inherited Protocol: "  << name << endl;
			return true;
		}
	}
	return m_zone->protocolInherited( name );
}

const QDomDocument& KMFNetHost::getDOMTree() {
	kdDebug() << "const QDomDocument& KMFNetHost::getDOMTree() " << endl;
	QDomDocument doc;
	QDomElement root = doc.createElement( "nethost" );
	root.setAttribute( "id", m_object_id );
	root.setAttribute( "name", m_name );
	root.setAttribute( "guiName", m_guiName );
	root.setAttribute( "description", m_desc );
	root.setAttribute( "address", m_address->toString() );
	if ( logIncoming() ) {
		root.setAttribute( "logIncoming", "bool:on" );
	} else {
		root.setAttribute( "logIncoming", "bool:off" );
	}
	if ( logOutgoing() ) {
		root.setAttribute( "logOutgoing", "bool:on" );
	} else {
		root.setAttribute( "logOutgoing", "bool:off" );
	}
	
	root.setAttribute( "limitRate", limitRate() );
	root.setAttribute( "limitScale", limitScale() );

	QPtrListIterator<KMFProtocol> it2 ( m_protocols );
	while (  it2.current() ) {
		root.appendChild(  it2.current()->getDOMTree( ) );
		++it2;
	}
	doc.appendChild( root );
	return *( new QDomDocument( doc ) );
}

void KMFNetHost::loadXML( const QDomDocument& doc ) {
// 	kdDebug() << "void KMFNetHost::loadXML( const QDomDocument& )" << endl;
	QDomElement root = doc.documentElement();
	QDomNode curr = root.firstChild();
	QString name = "";
	QString guiName = "";
	QString desc = "";
	QString address = "";
	QString logIn = "";
	QString logOut = "";
	QString limitRate = "";
	QString limitScale = "";	
	
	name = root.toElement().attribute( "name" );
	guiName = root.toElement().attribute( "guiName" );
	desc = root.toElement().attribute( "description" );
	address = root.toElement().attribute( "address" );
	logIn = root.toElement().attribute( "logIncoming" );
	logOut = root.toElement().attribute( "logOutgoing" );
	limitRate = root.toElement().attribute( "limitRate" );
	limitScale = root.toElement().attribute( "limitScale" );
	
	if ( logIn == "bool:on" ) {
		m_logIncoming = true;
	} else {
		m_logIncoming = false;
	}

	if ( logOut == "bool:on" ) {
		m_logOutgoing = true;
	} else {
		m_logOutgoing = false;
	}
	bool ok;
	int lRate = limitRate.toInt( &ok );
	if ( ok ) {
		setLimit( lRate, *( new QString( limitScale ) ) );
	}
	
	setDescription( *( new QString( desc ) ) );
	setName( *( new QString( name ) ) );
	setGuiName( *( new QString( guiName ) ) );
	this->address()->setAddress( address );

	while ( !curr.isNull() ) {
		if ( curr.isElement() && ( curr.nodeName() == "protocol" ) ) {
			QString name = "";
			name = curr.toElement().attribute( "name" );
			QDomDocument protocol_doc;
			protocol_doc.appendChild( curr.cloneNode(true) );
			addProtocol( name, protocol_doc );
		}
		curr = curr.nextSibling();
	}
}





