/***************************************************************************
 *
 * tdenetman-pluginmanager.cpp - A NetworkManager frontend for TDE 
 *
 * Copyright (C) 2006 Novell, Inc.
 *
 * Author: Helmut Schaa <hschaa@suse.de>, <helmut.schaa@gmx.de>
 *
 * 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
 *
 **************************************************************************/

#include <kplugininfo.h>
#include <tdeparts/componentfactory.h>
#include <kdebug.h>
#include <tdelocale.h>

#include "tdenetman-pluginmanager.h"

PluginManager* PluginManager::_instance;

PluginManager* PluginManager::getInstance()
{
	if (_instance) {
		return _instance;
	}
	return new PluginManager(TQT_TQOBJECT(TDENetworkManager::getInstance()), "pluginmanager");
}

PluginManager::PluginManager(TQObject* parent, const char* name)
	: TQObject(parent, name)
{
	// get list of available plugins
	this->_plugins = KPluginInfo::fromServices( TDETrader::self()->query( TQString::fromLatin1( "TDENetworkManager/Plugin" )));

	// a bit debug output
	for(TQValueList<KPluginInfo*>::ConstIterator it = _plugins.begin(); it != _plugins.end(); ++it) {
		kdDebug() << k_funcinfo << TQString("Found Plugin '%1'").arg((*it)->pluginName()) << endl;
	}
}

PluginManager::~PluginManager()
{
	// delete all loaded plugins
	while(!_loadedPlugins.empty()) {
		PluginMap::Iterator it = _loadedPlugins.begin();
		_loadedPlugins.remove(it);
	}

	// delete all available plugininfos
	while(!_plugins.empty()) {
		TQValueList<KPluginInfo*>::Iterator it = _plugins.begin();
		delete *it;
		_plugins.remove(it);
	}
}

TQStringList PluginManager::getPluginList(const TQString& serviceType, const TQString& property, const TQString& value) const
{
	TQStringList ret;
	// find a suitable plugin
	for(TQValueList<KPluginInfo*>::ConstIterator it = _plugins.begin(); it != _plugins.end(); ++it) {
		if ((*it)->service()->serviceTypes().contains(serviceType) > 0) {
			if ((*it)->property(property).toString().contains(value)) {
				ret.append( (*it)->pluginName() );
			}
		}
	}
	return ret;
}

Plugin* PluginManager::getPlugin(const TQString& pluginID)
{
	KPluginInfo* info = infoForPluginID(pluginID);
	if (_loadedPlugins.contains(info)) {
		return _loadedPlugins[info];
	}
	else {
		return loadPlugin(pluginID);
	}
	return NULL;
}

const KPluginInfo* PluginManager::getPluginInfo(const TQString& pluginID)
{
	return infoForPluginID(pluginID);
}

const KPluginInfo* PluginManager::getPluginInfo(const Plugin* plugin)
{
	for(PluginMap::ConstIterator it = _loadedPlugins.begin(); it != _loadedPlugins.end(); ++it) {
		if (it.data() == plugin)
			return it.key();
	}
	return NULL;
}

void PluginManager::loadAllPlugins()
{
	// iterate over all plugins
	for(TQValueList<KPluginInfo*>::ConstIterator it = _plugins.begin(); it != _plugins.end(); ++it) {
		// load Plugin
		loadPlugin((*it)->pluginName());
	}
}


Plugin* PluginManager::loadPlugin(const TQString& pluginID)
{
	// try to load Plugin
	int error = 0;
	KPluginInfo* info = infoForPluginID(pluginID);
	Plugin *plugin = KParts::ComponentFactory::createInstanceFromQuery<Plugin>( TQString::fromLatin1( "TDENetworkManager/Plugin" ),
	                 TQString::fromLatin1( "[X-TDE-PluginInfo-Name]=='%1'" ).arg( pluginID ), this, 0, TQStringList(), &error );

	// plugin loaded?
	if (plugin) {
		kdDebug() << k_funcinfo << TQString(i18n("successfully loaded plugin '%1'")).arg(info->pluginName()) << endl;
		_loadedPlugins.insert(info, plugin);
	}
	else {
		// error
		switch( error )
		{
		case KParts::ComponentFactory::ErrNoServiceFound:
			kdDebug( ) << k_funcinfo << "No service implementing the given mimetype "
			           << "and fullfilling the given constraint expression can be found." << endl;
			break;

		case KParts::ComponentFactory::ErrServiceProvidesNoLibrary:
			kdDebug( ) << "the specified service provides no shared library." << endl;
			break;

		case KParts::ComponentFactory::ErrNoLibrary:
			kdDebug( ) << "the specified library could not be loaded." << endl;
			break;

		case KParts::ComponentFactory::ErrNoFactory:
			kdDebug( ) << "the library does not export a factory for creating components." << endl;
			break;

		case KParts::ComponentFactory::ErrNoComponent:
			kdDebug( ) << "the factory does not support creating components of the specified type." << endl;
			break;
		}

		kdDebug() << k_funcinfo << "Loading plugin '" << pluginID << "' failed, KLibLoader reported error: '" << endl
		          << KLibLoader::self()->lastErrorMessage() << "'" << endl;

	}

	return plugin;
}

KPluginInfo * PluginManager::infoForPluginID( const TQString& pluginID ) const
{
	TQValueList<KPluginInfo *>::ConstIterator it;
	for ( it = this->_plugins.begin(); it != this->_plugins.end(); ++it ) {
		if ( ( *it )->pluginName() == pluginID ) {
			return *it;
		}
	}

	return 0L;
}

#include "tdenetman-pluginmanager.moc"
