/*======================================================================================

	Program:		Range Imaging Toolkit (RITK)
	Module:			ritkPluginManager.h
	Version:		$Revision: 1763 $
	Date:			$Date: 2011-09-25 20:22:20 +0200 (Sun, 25 Sep 2011) $

	Copyright (c) 2010-2011
	Pattern Recognition Lab, 
    University Erlangen-Nuremberg, Germany
    All rights reserved.

	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 RITKCopyright.txt for more information.

	http://www5.informatik.uni-erlangen.de/research/software/ritk

========================================================================================*/

#ifndef PLUGINMANAGER_H__
#define PLUGINMANAGER_H__

#include "ritkCore.h"

#include <QObject>
#include <QString>
#include <QList>
#include <QPluginLoader>
#include <QTreeWidgetItem>

#include "ritkPluginBase.h"

namespace ritk
{


/**	@ingroup	Core
 *	@class		PluginManager
 *	@author		Jakob Wasza / Sebastian Bauer
 *	@brief		Class  for managing plugins
 *
 *	@details
 *	This class implements functionality to manage plugins. In particular, this includes
 *	loading/unloading plugins.
 */
class PluginManager : public QObject
{
	Q_OBJECT

public:
	/// Constructor
	PluginManager();
	/// Destructor
	~PluginManager();

	/**	@brief	Update the internal list of available plugin loaders.
	 *	@param	Dir		The directory to scan
	 *
	 *	@details
	 *	This method will update the internal list of available plugin loaders.
	 *	In the first step all available loaders are checked if the corresponding DLL/SO is still valid.
	 *	Loaders that point to an invalid DLL/SO will be removed from the internal list. \n
	 *	The second step is to look for new loaders by recursively scanning the given directory for DLLs/SOs. 
	 *	For every encountered DLL/SO the following steps will be performed: \n
	 *		- Check the internal plugin loader list if the DLL/SO is already managed \n
	 *		- Check if the DLL/SO provides a valid plugin factory using a QPluginLoader\n
	 *		- If the checks pass, add the plugin loader to the internal list, otherwise discard it.\n
	 */
	void UpdateAvailablePluginLoaders(QString Dir);

	/// Plugin types
	enum PluginTypes
	{
		ImageType,
		Source,
		Filter,
		Application,
		Generic,
	};

	/// Struct that encapsulates a plugin loader and additional information
	typedef struct
	{
		/// The qloader for loading the plugin from file
		QPluginLoader *Loader;
		/// The type of the plugin
		PluginTypes PluginType;
		/// The module name (i.e. the file name of the shared lib)
		QString ModuleName;
		/// The plugin name as returned by the factory
		QString PluginName;
		/// The description as returned by the factory
		QString Description;
		/// Flag that indicated whether the plugin is started
		bool Started;
		/// The instance of the plugin
		PluginBase *InstancePointer;		
		/// The tree item of the plugin
		QTreeWidgetItem *TreeItem;
	} PluginStruct;

	/**	@brief	Returns the list of available plugins loaders.
	 *	@return	The list
	 *
	 *	@details
	 *	This method returns the list of available plugin loaders*/
	QList<PluginStruct>& GetAvailablePluginLoaders();

	/// Get the current plugin directory
	QString GetPluginDir();

signals:
	/// Emitted if the status of a plugin changes
	void PluginStatusChanged(PluginManager::PluginStruct&);

public slots:
	/// Connected to the plugin dialogs startplugin signal
	void StartPlugin(PluginManager::PluginStruct&);
	/// Connected to the signal emitted by the manager when the user wants to start a plugin and configure it with a given parameter hash
	void StartPluginAndConfigure(PluginManager::PluginStruct&, QHash<QString, QString>);
	/// Connected to the plugin dialogs stopplugin signal
	void StopPlugin(PluginManager::PluginStruct&);

protected:
	/// The current plugin directory
	QString m_PluginDir;
	/// The list of plugin loaders
	QList<PluginStruct> m_AvailablePluginLoaders;

};

} // end namespace ritk

#endif // PLUGINMANAGER_H__