/*
Copyright (C) 2012 Timothy Pearson <kb9vqf@pearsoncomputing.net>
Copyright 2008 Will Stephenson <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) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor approved
by the membership of KDE e.V.), which shall act as a proxy 
defined in Section 14 of version 3 of the license.

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, see <http://www.gnu.org/licenses/>.
*/

#include "devicetraycomponent.h"

#include <kdebug.h>
#include <tdelocale.h>
#include <kiconloader.h>
#include <ksystemtray.h>
#include <knotifyclient.h>
#include <knotifydialog.h>

TQString DeviceTrayComponent::pixmapForConnState(TDENetworkConnectionStatus::TDENetworkConnectionStatus state) {
	TDENetworkConnectionStatus::TDENetworkConnectionStatus flag = (TDENetworkConnectionStatus::TDENetworkConnectionStatus)0x80000000;
	while ((TQ_UINT32)flag > 0) {
		if (state & flag) {
			if (m_pixmaps.contains(flag)) {
				return m_pixmaps[flag];
			}
		}
		flag = (TDENetworkConnectionStatus::TDENetworkConnectionStatus)((TQ_UINT32)flag >> 1);
	}
	return TQString::null;
}

TQString DeviceTrayComponent::movieForConnState(TDENetworkConnectionStatus::TDENetworkConnectionStatus state) {
	TDENetworkConnectionStatus::TDENetworkConnectionStatus flag = (TDENetworkConnectionStatus::TDENetworkConnectionStatus)0x80000000;
	while ((TQ_UINT32)flag > 0) {
		if (state & flag) {
			if (m_movies.contains(flag)) {
				return m_movies[flag];
			}
		}
		flag = (TDENetworkConnectionStatus::TDENetworkConnectionStatus)((TQ_UINT32)flag >> 1);
	}
	return TQString::null;
}

TQString DeviceTrayComponent::tooltipForConnState(TDENetworkConnectionStatus::TDENetworkConnectionStatus state) {
	TDENetworkConnectionStatus::TDENetworkConnectionStatus flag = (TDENetworkConnectionStatus::TDENetworkConnectionStatus)0x80000000;
	while ((TQ_UINT32)flag > 0) {
		if (state & flag) {
			if (m_tooltips.contains(flag)) {
				return m_tooltips[flag];
			}
		}
		flag = (TDENetworkConnectionStatus::TDENetworkConnectionStatus)((TQ_UINT32)flag >> 1);
	}
	return TQString::null;
}

DeviceTrayComponent::DeviceTrayComponent(TQString device, KSystemTray * parent, const char * name )
    : TrayComponent(parent, name), m_tray(dynamic_cast<Tray*>(parent)), m_device(device)
{
	lastKnownState = TDENetworkConnectionStatus::Invalid;

	TDEHardwareDevices* hwdevices = TDEGlobal::hardwareDevices();

	// Trigger an initial hardware information update
	TDENetworkDevice* dev = dynamic_cast<TDENetworkDevice*>(hwdevices->findByUniqueID(m_device));
	TDENetworkConnectionManager* deviceConnMan = (dev ? dev->connectionManager() : NULL);

	if (deviceConnMan)
	{
		connect(deviceConnMan, TQ_SIGNAL(networkDeviceStateChanged(TDENetworkConnectionStatus::TDENetworkConnectionStatus, TDENetworkConnectionStatus::TDENetworkConnectionStatus, TQString)), TQ_SLOT(deviceStateChanged(TDENetworkConnectionStatus::TDENetworkConnectionStatus, TDENetworkConnectionStatus::TDENetworkConnectionStatus, TQString)));
		connect(deviceConnMan, TQ_SIGNAL(networkDeviceEvent(TDENetworkDeviceEventType::TDENetworkDeviceEventType, TQString)), this, TQ_SLOT(deviceEventHandler(TDENetworkDeviceEventType::TDENetworkDeviceEventType, TQString)));
	}

	m_pixmaps[TDENetworkConnectionStatus::Invalid] = "nm_no_connection";
	m_pixmaps[TDENetworkConnectionStatus::UnManaged] = "nm_no_connection";
	m_pixmaps[TDENetworkConnectionStatus::LinkUnavailable] = "nm_no_connection";
	m_pixmaps[TDENetworkConnectionStatus::Disconnected] = "nm_no_connection";
	m_pixmaps[TDENetworkConnectionStatus::Connected] = "ok";
	m_pixmaps[TDENetworkConnectionStatus::Failed] = "nm_no_connection";

	m_movies[TDENetworkConnectionStatus::EstablishingLink] = "nm_stage01_connecting";
	m_movies[TDENetworkConnectionStatus::ConfiguringProtocols] = "nm_stage02_connecting";
	m_movies[TDENetworkConnectionStatus::VerifyingProtocols] = "nm_stage03_connecting";
	m_movies[TDENetworkConnectionStatus::NeedAuthorization] = m_movies[TDENetworkConnectionStatus::ConfiguringProtocols];

	m_tooltips[TDENetworkConnectionStatus::Invalid] = i18n("Unknown");
	m_tooltips[TDENetworkConnectionStatus::LinkUnavailable] = i18n("Down");
	m_tooltips[TDENetworkConnectionStatus::UnManaged] = i18n("Unmanaged");
	m_tooltips[TDENetworkConnectionStatus::Disconnected] = i18n("Disconnected");
	m_tooltips[TDENetworkConnectionStatus::EstablishingLink] = i18n("Preparing");
	m_tooltips[TDENetworkConnectionStatus::ConfiguringProtocols] = i18n("Configuration");
	m_tooltips[TDENetworkConnectionStatus::NeedAuthorization] = i18n("Awaiting authentication");
	m_tooltips[TDENetworkConnectionStatus::VerifyingProtocols] = i18n("IP configuration");
	m_tooltips[TDENetworkConnectionStatus::Connected] = i18n("Activated");
	m_tooltips[TDENetworkConnectionStatus::Failed] = i18n("Failed");
}

DeviceTrayComponent::~DeviceTrayComponent()
{
}

TQString DeviceTrayComponent::device() const
{
	return m_device;
}

void DeviceTrayComponent::deviceEventHandler(TDENetworkDeviceEventType::TDENetworkDeviceEventType event, TQString message) {
	kdDebug() << "DeviceTrayComponent::deviceEventHandler" << endl;

	if (event == TDENetworkDeviceEventType::Failure) {
		KNotifyClient::event( tray()->winId(), "tdenm-nm-connection-attempt-failed", i18n(message.utf8()) );
	}
}

TQStringList DeviceTrayComponent::getToolTipText()
{
	TDEHardwareDevices* hwdevices = TDEGlobal::hardwareDevices();
	TDENetworkDevice* dev = dynamic_cast<TDENetworkDevice*>(hwdevices->findByUniqueID(m_device));

	TQStringList list;
	TDENetworkConnectionManager* deviceConnMan = (dev ? dev->connectionManager() : NULL);
	if (deviceConnMan)
	{
		TDENetworkConnectionStatus::TDENetworkConnectionStatus state = deviceConnMan->deviceStatus().statusFlags;
		if (tooltipForConnState(state) != "")
		{
			list.append(i18n("Device: %1").arg(dev->deviceNode()));
			list.append(i18n("State: %1").arg(tooltipForConnState(state)));
		}
	}
	return list;
}


TQPixmap DeviceTrayComponent::pixmapForState(TDENetworkConnectionStatus::TDENetworkConnectionStatus state)
{
	if (pixmapForConnState(state) != "") {
		TQString pixmapPath = pixmapForConnState(state);
		if (pixmapPath != "") {
			if (m_tray) {
				if (m_tray->m_pixmapCache.contains(pixmapPath)) {
					return m_tray->m_pixmapCache[pixmapPath];
				}
			}
			return KSystemTray::loadIcon(pixmapPath);
		}
		else {
			return TQPixmap();
		}
	}
	else {
		return TQPixmap();
	}
}

TQMovie DeviceTrayComponent::movieForState(TDENetworkConnectionStatus::TDENetworkConnectionStatus state)
{
	if (movieForConnState(state) != "") {
		TQString moviePath = movieForConnState(state);
		if (moviePath != "") {
			if (m_tray) {
				if (m_tray->m_movieCache.contains(moviePath)) {
					return TQMovie(m_tray->m_movieCache[moviePath]);
				}
			}
			if (m_tray) {
				return TQMovie(TDEGlobal::iconLoader()->moviePath(moviePath, TDEIcon::Panel, m_tray->width()));
			}
			else {
				return TQMovie(TDEGlobal::iconLoader()->moviePath(moviePath, TDEIcon::Panel));
			}
		}
		else {
			return TQMovie();
		}
	}
	else {
		return TQMovie();
	}
}

void DeviceTrayComponent::setMovieForState(TDENetworkConnectionStatus::TDENetworkConnectionStatus state, TQString movie)
{
	m_movies[state] = movie;
}

void DeviceTrayComponent::setPixmapForState(TDENetworkConnectionStatus::TDENetworkConnectionStatus state, TQString pixmap)
{
	m_pixmaps[state] = pixmap;
}

void DeviceTrayComponent::deviceStateChanged(TDENetworkConnectionStatus::TDENetworkConnectionStatus newState, TDENetworkConnectionStatus::TDENetworkConnectionStatus prevState, TQString deviceNode)
{
	lastKnownState = newState;

	TDEHardwareDevices* hwdevices = TDEGlobal::hardwareDevices();
	TDEGlobalNetworkManager* nm = TDEGlobal::networkManager();
	TDENetworkDevice* dev = dynamic_cast<TDENetworkDevice*>(hwdevices->findByUniqueID(m_device));

	if (!dev)
	{
		return;
	}
	if (dev->deviceNode() != deviceNode) {
		kdDebug() << k_funcinfo << "WARNING: Got networkDeviceStateChanged signal for interface '" << deviceNode << "', but my interface is '" << dev->deviceNode() << "'!  Ignoring...";
		return;
	}

#ifdef DEBUG_STATE
	printf("Device tray state: 0x%08x\n", newState);
#endif // DEBUG_STATE

	//check if our device now holds the default active connection
	// if it is the default active connection
	// or if it is activating.  what if 2 devices are activating simultaneously?
	if (newState & TDENetworkConnectionStatus::EstablishingLink) {
		TQTimer::singleShot(0, this, TQ_SLOT(sendGetCenterStage()));
	}
	else if (newState & TDENetworkConnectionStatus::Connected) {
		if (nm && nm->defaultNetworkDevices().contains(m_device))
		{
			TQTimer::singleShot(0, this, TQ_SLOT(sendGetCenterStage()));
		}
	}
	else if ((newState & TDENetworkConnectionStatus::LinkUnavailable)
		|| (newState & TDENetworkConnectionStatus::Disconnected)
		|| (newState & TDENetworkConnectionStatus::Failed)) {
		TQTimer::singleShot(0, this, TQ_SLOT(sendReleaseCenterStage()));
	}
}

void DeviceTrayComponent::sendGetCenterStage() {
	emit needsCenterStage(this, true);
}

void DeviceTrayComponent::sendReleaseCenterStage() {
	emit needsCenterStage(this, false);
}

#include "devicetraycomponent.moc"
