//
// Created by Ht on 2021/9/26.
//

#ifndef INC_0_LIBDEVCPP_CPAD_MGBUSSERVERSERVICE_H
#define INC_0_LIBDEVCPP_CPAD_MGBUSSERVERSERVICE_H

#include "src/MgBusServer.h"

namespace jedge {

    using ServerServiceCommandHandler = JE_API
            std::function <void(MgNodeRef& node,
                                      const std::string &src,
                                      const std::string &cmd,
                                      qlibc::QData &param,
                                      qlibc::QData &result)>;

    class JE_API MgbusServerService :
            public jedge::MgService ,
            public MgTriggerManagerOperator {
    protected:
        qlibc::QSharedObjectHolder<ServerServiceCommandHandler>*
                                    server_service_commands_ = nullptr;
    public:
        MgBusServer &getServer() {
            return *dynamic_cast<jedge::MgBusServer*>(&operator_);
        }

        qlibc::QSharedObjectHolder<ServerServiceCommandHandler>& getCommandHandlerPoot() {
            RECURSIVE_LOCK(service_mutex_);
            if(server_service_commands_ == nullptr) {
                server_service_commands_ = new qlibc::QSharedObjectHolder<ServerServiceCommandHandler>();
            }
            return *server_service_commands_;
        }

        MgbusServerService(MgBusServer &opr, const std::string &name, const qlibc::QData& config)
            : MgService ( opr, name, config, false), MgTriggerManagerOperator(dynamic_cast<ChannelOperator&>(opr)) {
        }

        void releaseCommandResources();

        ~MgbusServerService() override {
            releaseCommandResources();      //需要同时阻塞service和action的释放。
            waitForShareAccessReleased();   //等待自引用之外的引用释放。
        };

        void addCommandHandler(const std::string &cmd, const ServerServiceCommandHandler& handler);

        void removeCommandHandler(const std::string &cmd);

        virtual void releaseNodes() = 0;
        virtual std::shared_ptr<MgNode> findNode(const std::string &nodeKey) = 0;
        virtual bool existsNode(const std::string &nodeKey) = 0;
        virtual void addNode(const std::string &nodeKey, MgNodeRef& node) = 0;
        virtual void removeNode(const std::string &nodeKey) = 0;
        virtual bool reIndexNode(const std::string &nodeKey, const std::string &newKey) = 0;
        virtual void checkMainKeyFree(const std::string &nodeKey){};

        //检查已登录情况,true 已处理/false 未处理
        bool checkOldNodeExists(const std::string &sockKey, std::string &modKey, qlibc::QData &msg,
                                SocketMode mode, MgNodeRef& node, bool multiNode = false );
        //创建新登录节点
        virtual MgNodeRef
        tryLoginMgbusNode(QJsonSocketServer& server, SocketMode mode, const std::string& sockKey, const std::string &nameKey, qlibc::QData &msg);

        auto getTrigerService() ->  MgTriggerManager *   override;

        virtual bool handleServiceCommand(MgNodeRef &node,
                const std::string &src,
                const std::string &cmd,
                qlibc::QData &param,
                qlibc::QData &result);

        template<typename T>
        inline std::shared_ptr<T> findServerService(const std::string& svcKey) {
            auto org = getServer().findServiceRef(svcKey);
            auto ref = std::dynamic_pointer_cast<T>(org);
            return ref;
        }

        void printEventsDefined(Json::Value *ret) override;

    protected:
        bool postServiceCommand(const std::string &svc, const std::string &cmd, qlibc::QData &req,    qlibc::QData &rsp);

        void releaseServerCommandHandlers();

        //返回一个登录成功消息
        void returnloginOkMessage(const std::string& sockKey, SocketMode mode,
                                  qlibc::QData& msg, int code, const std::string& nameKey);

    };

#define BindCommandServiceHandlerR(func,r) \
    addCommandHandler(#func, [this,r](jedge::MgNodeRef& node, \
        const std::string &src,\
        const std::string &cmd,\
        qlibc::QData &param,\
        qlibc::QData &result){            \
            AssertAvailableVoid; \
            return cmd_##func(this,node,src,cmd,param,result); \
        })

#define BindCommandServiceHandler(func) \
    addCommandHandler(#func, [this, __self_r](jedge::MgNodeRef& node, \
        const std::string &src,\
        const std::string &cmd,\
        qlibc::QData &param,\
        qlibc::QData &result){            \
            AssertAvailableVoid; \
            return cmd_##func(this,node,src,cmd,param,result); \
        })

#define BindCommandServiceDefaultHandlerR(func,r)  \
    addCommandHandler(jedge::JEDGE_DEFAULT_SERVICE_COMMAND, [this,r](jedge::MgNode* node,\
        const std::string &src,\
        const std::string &cmd,\
        qlibc::QData &param,\
        qlibc::QData &result){                    \
            AssertAvailableValue(true); \
            return cmd_##func(this,node,src,cmd,param,result); \
        })

#define BindCommandServiceDefaultHandler(func,__self_r)  \
    addCommandHandler(jedge::JEDGE_DEFAULT_SERVICE_COMMAND, [this,r](jedge::MgNode* node,\
        const std::string &src,\
        const std::string &cmd,\
        qlibc::QData &param,\
        qlibc::QData &result){                    \
            AssertAvailableValue(true); \
            return cmd_##func(this,node,src,cmd,param,result); \
        })

#define ImplementCommandServiceHandler(func,svc,n,s,c,p,r) \
        void cmd_##func(jedge::MgbusServerService* svc,MgNodeRef& n,\
        const std::string &s,\
        const std::string &c,\
        qlibc::QData &p,\
        qlibc::QData &r)
}

#endif //INC_0_LIBDEVCPP_CPAD_MGBUSSERVERSERVICE_H
