//
// Created by Ht on 2022/1/7.
//

#ifndef INC_1_LIBDEVCPP_QPLUGINMANAGER_H
#define INC_1_LIBDEVCPP_QPLUGINMANAGER_H

#include <jebase/config.h>
#include <string>
#include <utility>
#include <cross/DllUtil.h>
#include <qlibc/QPObjectHolder.h>

#include "QPluginEntry.h"


namespace qlibc {

    typedef QPluginEntry* (*QEntryCreator)(void*handler);
    typedef void (*QEntryReleaser)(QPluginEntry* entry);

/**
 * 扫描一个指定的目录，并针对指定的初始化函数进行调用、创建一个个的Entry对象
 */
    class JE_API QPluginManager {
    protected:
        std::string base_path_;
        std::string plug_type_;
        int         least_ver_;
        QPObjectHolder<QPluginEntry> entries_;      //通常只在初始化和管理使用，目前暂不考虑用动态内存管理。

        virtual QPluginEntry* createPluginEntry(void *handle);

        virtual void releasePluginEntry(QPluginEntry *entry);

        void closeEntryPtr(QPluginEntry *pEntry);

    public:
        explicit QPluginManager(std::string basePath, std::string type = "", int lestVer = -1);

        virtual ~QPluginManager();;

        //扫描、加载特定类型的插件
        void scanPlugins();

        void manualPushPlugin(QPluginEntry *entry) {
            entries_.appendNew(entry->getPluginName(), entry);
        }

        void releaseAllEntries();

        template <typename T = QPluginEntry>
        T *findEntry(const std::string &key) {
            auto* e = entries_.findObject(key);
            return e== nullptr? nullptr:dynamic_cast<T*>(e);
        }

        //加载特定路径的插件
        QPluginEntry* loadEntry(const std::string& fn);

        //关闭特定key的entry
        void closeEntry(const std::string &key);

        void getPluginKeySets(QStringList& keys);
    };
}
#endif //INC_1_LIBDEVCPP_QPLUGINMANAGER_H
