#ifndef SH_PLUGINS_LOADER_H
#define SH_PLUGINS_LOADER_H

#include <QDir>
#include <piplugin.h>
#include "SH_plugin_base.h"
#include "SH_plugin_manifest.h"

class SHPluginsLoader: public QObject {
	Q_OBJECT
public:
	SHPluginsLoader();
	~SHPluginsLoader();
	
	struct PluginInfo {
		QString key() const;
		QString displayType() const;
		QString fullName() const;
		SHPluginManifest manifest;
		SHPluginBase * plugin = nullptr;
		SHPluginBase::PluginType type = SHPluginBase::None;
		SHPluginBase::PluginFlags flags = SHPluginBase::PluginFlags();
	};
	struct PluginLibrary {
		bool isLoaded() const;
		bool isDisabled() const;
		bool isError() const;
		bool load(bool force = false);
		void unload();
		SHPluginManifest manifest;
		PIPluginLoader * library = nullptr;
		PIVector<PluginInfo> plugins;
		QString load_error;
		SHPluginsLoader * parent = nullptr;
	};
	
	void loadPlugins();
	bool loadPlugin(const SHPluginManifest & manifest, bool force = false);
	bool loadPlugin(const QString & name, bool force = false);
	void unloadPlugins();
	void unloadPlugin(const QString & name);
	void removePlugin(const QString & name);
	void enablePlugin(const QString & name);
	void disablePlugin(const QString & name);
	PluginInfo getPlugin(const QString & name, SHPluginBase::PluginType type) const;
	PluginInfo getPlugin(uint id) const;
	PIVector<PluginInfo> getPlugins(SHPluginBase::PluginType type) const;
	PIVector<PluginInfo> loadedPlugins() const;
	const PIMap<QString, PluginLibrary> & readedLibraries() const {return plugin_libraries;}
	QString webDirectory() const {return web_dir;}
	void readManifests();

	static void addBuiltinPlugin(SHPluginBase * p);
	
protected:
	bool registerPlugin(const PluginInfo & pi);
	void saveDisabled();
	
	PIMap<uint, PluginInfo> plugin_by_id;
	PIMap<QString, PluginLibrary> plugin_libraries; // by name in manifest
	QStringList disabled;
	QString web_dir;
	PIString disabled_filepath;

	static QList<PluginInfo> & builtinPlugins();
	
public slots:
	
signals:
	void loaded();
	void aboutUnload();
	void aboutUnloadPlugin(SHPluginBase * );
	
};

#endif
