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

#ifndef INC_0_LIBDEVCPP_QJASERVICEENTRY_H
#define INC_0_LIBDEVCPP_QJASERVICEENTRY_H

#include <qlibc/plugin/QPluginEntry.h>
#include "QJAService.h"
#include <memory>

namespace jedge {

    class JE_API QJAPluginService :
            public jedge::QJAMgService {
    public:
        explicit QJAPluginService(jedge::QJAMgServer& opr, const std::string &name, const qlibc::QData &config);

#ifdef ANDROID
        jedge::MgBusHolder *getHolder() override {
            return (jedge::MgBusHolder*)(&operator_);
        }

    protected:
        auto getTrigerService() -> MgTriggerManager * override {
            auto* holder = getHolder();
            auto* s = holder==nullptr?nullptr:holder->findService(JEDGE_MGBUS_EVENT_SERVICE_NAME);
            return (s == nullptr)?(nullptr):(MgTriggerManager*)(s);
        }
#endif

    };

    class JE_API QJAClassExtEntry :
            public qlibc::QPluginEntry {
    public:
        explicit QJAClassExtEntry(std::string name, std::string type = "", int ver = 0);

        ~QJAClassExtEntry() override { }

        virtual void loadInnerClasses(jedge::QJAMgServer& server) = 0;

        virtual void releaseClasses(QJAMgServer &server) = 0;
    };

    using QJAPluginServiceCreator = std::function<QJAPluginService*(jedge::QJAMgServer& server, const std::string &name, const qlibc::QData &config)>;

    class JE_API QJAServiceEntry :
        public qlibc::QPluginEntry {
    protected:
        QJAPluginService* service_ = nullptr;
        QJAPluginServiceCreator* creator_ = nullptr;
    public:
        explicit QJAServiceEntry(std::string name, std::string type = "service", int ver = 0);

        ~QJAServiceEntry() override;

        void setServiceCreator(const QJAPluginServiceCreator& cr);

        virtual QJAPluginService * getPluginService(QJAMgServer& server);
    };

    using QPluginServiceList = std::vector<QJAPluginService*>;

    class JE_API QJAMultiServiceEntry :
        public qlibc::QPluginEntry {
    protected:
        qlibc::QPObjectHolder<QJAPluginServiceCreator> creators_;
    public:
        explicit QJAMultiServiceEntry(std::string name, std::string type = "multiService", int ver = 0) :
            qlibc::QPluginEntry(std::move(name), std::move(type), ver) {
        }

        ~QJAMultiServiceEntry() override {}

        void bindServiceCreator(const std::string& key, const QJAPluginServiceCreator& cr);

        //每个service复制一个引用
        virtual std::shared_ptr<QPluginServiceList> getPluginService(QJAMgServer& server);
    };

#define DefinePluginService(_e, _cls) \
        ((QJAServiceEntry*)(_e))->setServiceCreator([](jedge::QJAMgServer& _s, const std::string &_n, const qlibc::QData &_c)->QJAPluginService* { \
            return new _cls(_s,_n,_c); \
        })

#define BindMultiPluginService(_e, _k, _cls) \
        ((QJAMultiServiceEntry*)(_e))->bindServiceCreator(_k, [](jedge::QJAMgServer& _s, const std::string &_n, const qlibc::QData &_c)->QJAPluginService* { \
            return new _cls(_s,_n,_c); \
        })
}

#endif //INC_0_LIBDEVCPP_QJASERVICEENTRY_H
