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

/***************************************************************************
 *                                                                         *
 *   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"

// static stuff
int NetfilterObject::m_last_given_id = -1;
QPtrList<NetfilterObject>* NetfilterObject::m_all_objects = new QPtrList<NetfilterObject>;
QIntDict<NetfilterObject>* NetfilterObject::m_dict_all_objects = new QIntDict<NetfilterObject>;

void NetfilterObject::resetNextObjectID() {
// 	kdDebug() << "NetfilterObject::resetNextObjectID()" << endl;
	m_last_given_id = -1;
}

NetfilterObject::NetfilterObject( QObject *parent ) : QObject( parent ) {
	m_parent = 0;
	m_doc = 0;
	if ( NetfilterObject * par = dynamic_cast<NetfilterObject*>( parent ) )
		m_parent = par;

	if ( KMFDoc * par = dynamic_cast<KMFDoc*>( parent ) )
		m_doc = par;

	setName( i18n( "Untitled" ) );
	setDescription( i18n( "No Description Available" ) );
	m_object_type = -1;
	m_last_given_id++;
	// 	kdDebug() << "Asigning new Object ID: " <<  m_last_given_id << endl;
	setObjectID( m_last_given_id );
	m_all_objects->append( this );
	m_dict_all_objects->insert( m_object_id , this );
}

NetfilterObject::~NetfilterObject() {
	QString tmp_type ="";
	if ( type() == RULEOPTION )
		tmp_type = "RULEOPTION";

	if ( type() == RULE )
		tmp_type = "RULE";

	if ( type() == CHAIN )
		tmp_type = "CHAIN";

	if ( type() == TABLE )
		tmp_type = "TABLE";

	if ( type() == NETHOST )
		tmp_type = "NETHOST";

	if ( type() == NETZONE )
		tmp_type = "NETZONE";

	if ( type() == PROTOCOL )
		tmp_type = "PROTOCOL";
	kdDebug() << "NetfilterObject: Deleting " << tmp_type << " with objectID: " << objectID()  << endl;



	if ( ! m_dict_all_objects->remove
	        ( objectID() ) )
		kdDebug() << "Could not delete object from NetfilterObject::m_dict_all_objects" << endl;
	if ( ! m_all_objects->remove
	        ( this ) )
		kdDebug() << "Could not delete object from NetfilterObject::m_all_objects" << endl;
}

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

bool NetfilterObject::isChildOf( int id ) {
	if ( ! m_parent )
		return false;
	if ( m_parent->objectID() == id )
		return true;
	return false;
}


void NetfilterObject::setName( const QString& name ) {
	if ( name.isNull() )
		return ;
	m_name = name;
}

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

void NetfilterObject::save() {
	m_saved = true;
}

void NetfilterObject::saveState() {
	QString XML = "";
	XML = getXMLSniplet();
	if ( ! m_undo_list.empty() && *m_undo_list.at( m_undo_list.count() - 1 ) == XML ) {
// 		kdDebug() << "NetfilterObject::saveState(): No changes to save." << endl;
		return ;
	}
	m_undo_list << XML;
	while ( m_undo_list.count() > KMFDoc::maxUndo() )
		m_undo_list.pop_front();
// 	kdDebug() << "Now storing: " << m_undo_list.count() << " undo steps" << endl;
}

void NetfilterObject::undoSaveState() {
// 	kdDebug() << "void NetfilterObject::undoSaveState()" << endl;
	if ( m_undo_list.count() > 0 ) {
// 		kdDebug() << "NetfilterObject::undoSaveState(): Removing obsolete undo step" << endl;
		m_undo_list.pop_back();
	}
}

void NetfilterObject::undo() {
// 	kdDebug() << "void NetfilterObject::undo()" << endl;
// 	kdDebug() << "Object ID: " << m_object_id << " Type: " << m_object_type << endl;
	if ( m_undo_list.empty() ) {
// 		kdDebug() << "NetfilterObject: No undo steps stored" << endl;
		return ;
	}
	QString redo_xml = getDOMTree().toString();
	m_redo_list << redo_xml;

	QString XML = *m_undo_list.at( m_undo_list.count() - 1 );
// 	kdDebug() << "Loading XML: " << XML << endl;
	m_undo_list.pop_back();

	QDomDocument doc;
	doc.setContent( XML );
	loadXML( doc );
}

void NetfilterObject::redo() {
// 	kdDebug() << "void NetfilterObject::redo()" << endl;
// 	kdDebug() << "Object ID: " << m_object_id << " Type: " << m_object_type << endl;
	if ( m_redo_list.empty() ) {
		kdDebug() << "NetfilterObject: No redo steps stored" << endl;
		return ;
	}
	QString undo_xml = getDOMTree().toString();
	m_undo_list << undo_xml;

	QString XML = *m_redo_list.at( m_redo_list.count() - 1 );
// 	kdDebug() << "Loading XML: " << XML << endl;
	m_redo_list.pop_back();

	QDomDocument doc;
	doc.setContent( XML );
	loadXML( doc );
}


void NetfilterObject::setObjectID( int id ) {
	m_object_id = id;
}

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

void NetfilterObject::changed() {
// 	kdDebug() << "void NetfilterObject::changed()" << endl;
	if ( NetfilterObject * parent = dynamic_cast<NetfilterObject*>( m_parent ) )
		parent->changed( m_object_id );
	else if ( KMFDoc * parent = dynamic_cast<KMFDoc*>( m_doc ) )
		parent->changed( m_object_id );
	m_saved = false;
}

void NetfilterObject::changed( int id ) {
// 	kdDebug() << "void NetfilterObject::changed( int " << id << " )" << endl;
	if ( NetfilterObject * parent = dynamic_cast<NetfilterObject*>( m_parent ) )
		parent->changed( id );
	else if ( KMFDoc * parent = dynamic_cast<KMFDoc*>( m_doc ) )
		parent->changed( id );
}
