/***************************************************************************
 *
 * knetworkmanager-device.cpp - A NetworkManager frontend for KDE 
 *
 * Copyright (C) 2005, 2006 Novell, Inc.
 *
 * Author: Timo Hoenig     <thoenig@suse.de>, <thoenig@nouse.net>
 *         Will Stephenson <wstephenson@suse.de>, <wstephenson@kde.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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 **************************************************************************/

// KDE includes
#include <kdebug.h>

// TQtDBus includes
#include <tqdbusconnection.h>
#include <tqdbusproxy.h>
#include <tqdbusdata.h>
#include <tqdbusdatalist.h>
#include <tqdbuserror.h>
#include <tqdbusobjectpath.h>

// NM includes
#include <NetworkManager.h>

// KNM includes
#include "knetworkmanager.h"
#include "knetworkmanager-nm_proxy.h"
#include "knetworkmanager-device.h"
#include "knetworkmanager-devicestore.h"
#include "knetworkmanager-connection.h"
#include "knetworkmanager-connection_store.h"
#include "dbus/activeconnectionproxy.h"

class NMProxyPrivate
{
	public:
		NMProxyPrivate()
		{}

		static NMProxy* nm;
};

NMProxy* NMProxyPrivate::nm = NULL;

Device* NMProxy::getDefaultDevice()
{
	TQT_DBusObjectPath connpath = getDefaultActiveConnection();
	if (!connpath.isEmpty())
	{
		TQT_DBusObjectPath devpath = getDeviceForActiveConnection(connpath);
		if (!devpath.isEmpty())
			return DeviceStore::getInstance()->getDevice(devpath);
	}
	return NULL;
}

TQT_DBusObjectPath NMProxy::getDeviceForActiveConnection(TQT_DBusObjectPath act_conn_path)
{
	TQT_DBusError      err;

	// we need a proxy for every active connection
	DBus::ActiveConnectionProxy* act_conn = new DBus::ActiveConnectionProxy(NM_DBUS_SERVICE, act_conn_path);
	act_conn->setConnection(TQT_DBusConnection::systemBus());

	if (act_conn)
	{
		// get details about the active connection
		TQValueList<TQT_DBusObjectPath> devs   = act_conn->getDevices(err);
		if (!devs.isEmpty())
			return devs.first();
		delete act_conn;
	}
	
	return TQT_DBusObjectPath();

}

TQT_DBusObjectPath NMProxy::getDefaultActiveConnection()
{
	TQT_DBusError      err;
	TQValueList<TQT_DBusObjectPath> connections;

	// get a list of all active connections from NM
	connections = NetworkManagerProxy::getActiveConnections(err);

	for (TQValueList<TQT_DBusObjectPath>::Iterator it = connections.begin(); it != connections.end(); ++it)
	{
		// we need a proxy for every active connection
		DBus::ActiveConnectionProxy* act_conn = new DBus::ActiveConnectionProxy(NM_DBUS_SERVICE, (*it));
		act_conn->setConnection(TQT_DBusConnection::systemBus());

		if (act_conn)
		{
			if (act_conn->getDefault(err))
			{
				delete act_conn;
				return *it;
			}
			delete act_conn;
		}
	
	}

	return TQT_DBusObjectPath();

}

ConnectionSettings::Connection* NMProxy::getActiveConnection(const Device* dev)
{
	TQT_DBusError      err;
	TQValueList<TQT_DBusObjectPath> connections;

	// get a list of all active connections from NM
	connections = NetworkManagerProxy::getActiveConnections(err);

	for (TQValueList<TQT_DBusObjectPath>::Iterator it = connections.begin(); it != connections.end(); ++it)
	{
		// we need a proxy for every active connection
		DBus::ActiveConnectionProxy* act_conn = new DBus::ActiveConnectionProxy(NM_DBUS_SERVICE, (*it));
		act_conn->setConnection(TQT_DBusConnection::systemBus());

		if (act_conn)
		{
			// get details about the active connection
			TQString         service      = act_conn->getServiceName(err);
			TQT_DBusObjectPath conn         = act_conn->getConnection(err);
			TQT_DBusObjectPath specific_obj = act_conn->getSpecificObject(err);
			TQValueList<TQT_DBusObjectPath> devs   = act_conn->getDevices(err);
			for (TQValueList<TQT_DBusObjectPath>::Iterator it2 = devs.begin(); it2 != devs.end(); ++it2)
			{
				if (TQString(*it2) == dev->getObjectPath())
				{
					// here is the connection we were looking for
					ConnectionStore* cstore = ConnectionStore::getInstance();
					if (cstore)
						return cstore->getConnection(TQString(conn));
				}
			}
			delete act_conn;
		}
	
	}

	return NULL;
}

TQValueList<TQPair<ConnectionSettings::Connection*, Device*> > NMProxy::getActiveConnectionsMap()
{
	TQT_DBusError      err;
	TQValueList<TQT_DBusObjectPath> connections;
	TQValueList<TQPair<ConnectionSettings::Connection*, Device*> > map;
	ConnectionStore* cstore = ConnectionStore::getInstance();
	DeviceStore* dstore = DeviceStore::getInstance();
	bool found = false;

	if (!dstore || !cstore)
		return map;

	// get a list of all active connections from NM
	connections = NetworkManagerProxy::getActiveConnections(err);

	for (TQValueList<TQT_DBusObjectPath>::Iterator it = connections.begin(); it != connections.end(); ++it)
	{
		// we need a proxy for every active connection
		DBus::ActiveConnectionProxy* act_conn = new DBus::ActiveConnectionProxy(NM_DBUS_SERVICE, (*it));
		act_conn->setConnection(TQT_DBusConnection::systemBus());

		if (act_conn)
		{
			// get details about the active connection
			TQString         service      = act_conn->getServiceName(err);
			TQT_DBusObjectPath conn         = act_conn->getConnection(err);
			TQT_DBusObjectPath specific_obj = act_conn->getSpecificObject(err);
			TQValueList<TQT_DBusObjectPath> devs   = act_conn->getDevices(err);
			found = false;
			for (TQValueList<TQT_DBusObjectPath>::Iterator it2 = devs.begin(); it2 != devs.end(); ++it2)
			{
				Device* device = dstore->getDevice(*it2);
				ConnectionSettings::Connection* connection = cstore->getConnection(TQString(conn));
				if (connection)
				{
					map.append(TQPair<ConnectionSettings::Connection*, Device*>(connection, device));
					found = true;
				}
			}
			if (!found)
			{
				// no device found for this connection -> just add it without device
				ConnectionSettings::Connection* connection = cstore->getConnection(TQString(conn));
				if (connection)
					map.append(TQPair<ConnectionSettings::Connection*, Device*>(connection, NULL));
			}
			delete act_conn;
		}
	
	}

	return map;
}

NMProxy::NMProxy()
	: NetworkManagerProxy(NM_DBUS_SERVICE, NM_DBUS_PATH)
{
	d = new NMProxyPrivate();
	NetworkManagerProxy::setConnection(TQT_DBusConnection::systemBus());
}

void NMProxy::deactivateConnection(const ConnectionSettings::Connection* conn, const Device* dev)
{
	TQT_DBusError      err;
	TQValueList<TQT_DBusObjectPath> connections;

	// get a list of all active connections from NM
	connections = NetworkManagerProxy::getActiveConnections(err);

	for (TQValueList<TQT_DBusObjectPath>::Iterator it = connections.begin(); it != connections.end(); ++it)
	{
		// we need a proxy for every active connection
		DBus::ActiveConnectionProxy* act_conn = new DBus::ActiveConnectionProxy(NM_DBUS_SERVICE, (*it));
		act_conn->setConnection(TQT_DBusConnection::systemBus());

		if (act_conn)
		{
			if (act_conn->getConnection(err) == conn->getObjectPath())
			{
				if (dev)
				{
					// get details about the active connection
					TQValueList<TQT_DBusObjectPath> devs   = act_conn->getDevices(err);
					for (TQValueList<TQT_DBusObjectPath>::Iterator it2 = devs.begin(); it2 != devs.end(); ++it2)
					{
						if (TQString(*it2) == dev->getObjectPath())
						{
							// this is the right one
							DeactivateConnection(*it, err);
							return;
						}
					}
				}
				else
				{
					DeactivateConnection(*it, err);
				}
			}
			delete act_conn;
		}
	}

}

void NMProxy::deactivateConnectionPath(TQT_DBusObjectPath obj_path)
{
	TQT_DBusError err;
	DeactivateConnection(obj_path, err);
}

void NMProxy::deactivateDevice(const Device* dev)
{
	TQT_DBusError      err;
	TQValueList<TQT_DBusObjectPath> connections;

	// get a list of all active connections from NM
	connections = NetworkManagerProxy::getActiveConnections(err);

	for (TQValueList<TQT_DBusObjectPath>::Iterator it = connections.begin(); it != connections.end(); ++it)
	{
		// we need a proxy for every active connection
		DBus::ActiveConnectionProxy* act_conn = new DBus::ActiveConnectionProxy(NM_DBUS_SERVICE, (*it));
		act_conn->setConnection(TQT_DBusConnection::systemBus());

		if (act_conn)
		{
			// get details about the active connection
			TQValueList<TQT_DBusObjectPath> devs   = act_conn->getDevices(err);
			for (TQValueList<TQT_DBusObjectPath>::Iterator it2 = devs.begin(); it2 != devs.end(); ++it2)
			{
				if (TQString(*it2) == dev->getObjectPath())
				{
					// this is the right one
					DeactivateConnection(*it, err);
					return;
				}
			}
			delete act_conn;
		}
	}
}

bool NMProxy::isNMRunning()
{
	// Ask DBus if the NetworkManager service is available
	TQT_DBusProxy* proxy = new TQT_DBusProxy("org.freedesktop.DBus", "/", "org.freedesktop.DBus", TQT_DBusConnection::systemBus());
	TQValueList<TQT_DBusData> params;
	params.append(TQT_DBusData::fromString(NM_DBUS_SERVICE));
	TQT_DBusMessage reply = proxy->sendWithReply("NameHasOwner", params);
	bool ret = reply.first().toBool();
	delete proxy;
	return ret;
}

NMProxy::~NMProxy()
{
	delete d;
}

NMProxy* NMProxy::getInstance()
{
	if (NMProxyPrivate::nm)
		return NMProxyPrivate::nm;
	return (NMProxyPrivate::nm = new NMProxy());
}


#include "knetworkmanager-nm_proxy.moc"
