/***************************************************************************
 *   Copyright (C) 2008 by Andreas Silberstorff   *
 *   taki@Rivendell   *
 *                                                                         *
 *   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 "pluginmanager.h"

#include "pluginfactory.h"
#include <PluginInterface>

#include <QDir>
#include <QApplication>
#include <QPluginLoader>
#include <QStringList>
#include <QStringListIterator>

#include <KStandardDirs>
#include <KConfigDialog>
#include <klocale.h>
#include <kglobal.h>
#include <KDebug>

namespace KalvaPluginSystem {

QList<QObject *> PluginManager::plugins()
{
	if ( m_plugins.empty() )
	{
		findPlugins();
	}
	return m_plugins;
}

QList<PluginFactory *> PluginManager::factories()
{
	if ( m_plugins.empty() )
	{
		findPlugins();
	}
	return m_factories;
}

QList<PluginFactory *> PluginManager::perspectives()
{
	if (! m_perspectives.empty() )
	{
		return m_perspectives;
	}
	if ( m_plugins.empty() )
	{
		findPlugins();
	}
        for (int i = 0; i < m_factories.size(); ++i) {
		PluginFactory *factory = (m_factories.at(i));
		if ( factory->perspective() != 0 )
		{
			m_perspectives.append( factory );
		}
	}
	return m_perspectives;
}

QList<PluginFactory *> PluginManager::devices()
{
	if (! m_devices.empty() )
	{
		return m_devices;
	}
	if ( m_plugins.empty() )
	{
		findPlugins();
	}
        for (int i = 0; i < m_factories.size(); ++i) {
		PluginFactory *factory = m_factories.at(i);
		if ( factory->device() != 0 )
		{
			m_devices.append( factory );
		}
	}
	return m_devices;
}

QList<PluginFactory *> PluginManager::schedulers()
{
 	if (! m_schedulers.empty() )
 	{
 		return m_schedulers;
 	}
 	if ( m_plugins.empty() )
 	{
 		findPlugins();
 	}
         for (int i = 0; i < m_factories.size(); ++i) {
 		PluginFactory *factory = m_factories.at(i);
 		if ( factory->scheduler() != 0 )
 		{
 			m_schedulers.append( factory );
 		}
 	}
	return m_schedulers;
}

QList<PluginFactory *> PluginManager::channellistproviders()
{
 	if (! m_channellistproviders.empty() )
 	{
 		return m_channellistproviders;
 	}
 	if ( m_plugins.empty() )
 	{
 		findPlugins();
 	}
         for (int i = 0; i < m_factories.size(); ++i) {
 		PluginFactory *factory = m_factories.at(i);
 		if ( factory->channellistprovider() != 0 )
 		{
 			m_channellistproviders.append( factory );
 		}
 	}
	return m_channellistproviders;
}

KalvaPlugin::DeviceInterface* PluginManager::device(QString titel) {
	kDebug() << "device( " << titel << " )";

	QList<KalvaPluginSystem::PluginFactory *> factories =
		KalvaPluginSystem::PluginManager::instance().devices();

        for (int id = 0; id < factories.size(); ++id)
	{
		KalvaPluginSystem::PluginFactory* factory = factories.at(id);
		KalvaPlugin::PluginInterface* plugin = factory->plugin();
		if (plugin->title() == titel) {
			return factory->device();
		}
	}
	return 0;
}

KalvaPlugin::ChannellistProviderInterface* PluginManager::channellistprovider(QString titel) {
	kDebug() << "device( " << titel << " )";

	QList<KalvaPluginSystem::PluginFactory *> factories =
		KalvaPluginSystem::PluginManager::instance().channellistproviders();

        for (int id = 0; id < factories.size(); ++id)
	{
		KalvaPluginSystem::PluginFactory* factory = factories.at(id);
		KalvaPlugin::PluginInterface* plugin = factory->plugin();
		if (plugin->title() == titel) {
			return factory->channellistprovider();
		}
	}
	return 0;
}

KalvaPlugin::SchedulerInterface* PluginManager::scheduler(QString titel) {
	kDebug() << "scheduler( " << titel << " )";

	QList<KalvaPluginSystem::PluginFactory *> factories =
		KalvaPluginSystem::PluginManager::instance().schedulers();

        for (int id = 0; id < factories.size(); ++id)
	{
		KalvaPluginSystem::PluginFactory* factory = factories.at(id);
		KalvaPlugin::PluginInterface* plugin = factory->plugin();
		if (plugin->title() == titel) {
			return factory->scheduler();
		}
	}
	return 0;
}

// adds config pages defined by the plugin to the applications config dialog
void PluginManager::addToConfigDialog( KConfigDialog *dialog )
{
	kDebug() << "addToConfigDialog()";
        for (int i = 0; i < m_factories.size(); ++i) {
		PluginFactory *factory = m_factories.at(i);
		if ( factory->isEnabled() )
		{
			kDebug() << "addToConfigDialog( " << factory->plugin()->title() << ")";
 			factory->addToConfigDialog( dialog );
			kDebug() << "added to configDialog( " << factory->plugin()->title() << ")";
 		}
	}
}

// informs all active perspectives
void PluginManager::settingsChanged()
{
	kDebug() << "settingsChanged()";
        for (int i = 0; i < m_factories.size(); ++i) {
             m_factories.at(i)->settingsChanged();
	}
}

void PluginManager::findPlugins()
{
	KStandardDirs *stdDirs = new KStandardDirs();
	QStringList paths = stdDirs->resourceDirs( "qtplugins" );
	QStringListIterator javaStyleIterator(paths);
	while (javaStyleIterator.hasNext())
	{
		QDir pluginsDir = QDir( javaStyleIterator.next() + "kalva2" );

		kDebug() << "pluginsDir = " << pluginsDir;
	
		foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
			kDebug() << "fileName = " << fileName;
			QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
			QObject *plugin = loader.instance();

		        if (plugin) {
				kDebug() << "plugin = " << plugin;
				// hinder plugins being loaded more then once because of version postfixes
				if ( ! m_plugins.contains( plugin ) )
				{
					kDebug() << "appendFactory(plugin)";
					appendFactory( plugin );
				}
		        } else
			{
				kDebug() << "loader->errorString() = " << loader.errorString();
			}
		}
	}
}

void PluginManager::setTabWidget( QTabWidget *manager )
{
        m_manager = manager;
}

void PluginManager::setMainViewStackedWidget( QStackedWidget *mainViewStack )
{
        m_mainViewStack = mainViewStack;
}

// creates the perspective with the widgets provided by the plugin
void PluginManager::appendFactory(QObject *plugin)
{
	m_plugins.append( plugin );
	kDebug() << "registered plugin " << plugin;

	PluginFactory *factory = new PluginFactory(
		m_manager, m_mainViewStack,
		plugin
	);


	m_factories.append( factory );

// TODO ...only set enabled on loading of kalvaview untill storing of settings is working!!!
	factory->setEnabled(true);
}

}