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

#ifndef INC_0_LIBDEVCPP_CPAD_MGSERVICE_H
#define INC_0_LIBDEVCPP_CPAD_MGSERVICE_H

#include "MgDataChannel.h"
#include "MgEventWatcher.h"
#include "MgTriggerManager.h"
#include "MgVersionShower.h"

namespace jedge {

    using ServiceMessageHandler = JE_API std::function<bool(qlibc::QData &message, qlibc::QData *response)>;
#ifdef DEBUG
    using ServiceMessageHandlerList = JE_API std::vector<std::pair<std::string, ServiceMessageHandler>>;
#else
    using ServiceMessageHandlerList = JE_API std::vector<std::pair<std::regex, ServiceMessageHandler>>;
#endif

    class JE_API MgService :
            public MgVersionShower,
            public MgDataChannel {
    protected:
        QStringList uri_patterns_;
        ServiceMessageHandlerList uri_map_;
        qlibc::QData config_;

        std::string host_sn_;

        MgWatcherPool*  mOutGoingWatchersPool_ = nullptr;
        bool        auto_remove_call_info:1;
        bool        active_:1;
        bool        auto_release_:1;
        qlibc::QRTimer out_going_watcher_timer_ = nullptr;
        std::recursive_mutex  service_mutex_;

    public:
        explicit MgService(ChannelOperator &opr, const std::string &name, const qlibc::QData &config, bool clrJedgeCall);

        ~MgService() override ;

        //获得来自其它通道的数据泵入
        bool postRawMessage(qlibc::QData &message) override;

        const QStringList &uriPatterns() {
            return uri_patterns_;
        }

        const std::string &getVersionHolderName() override;

        void clearServicePattern() {
            uri_patterns_.clear();
        }

        MgWatcherPool& getWatcherPool();

        //在派生对象中调用 PATTERN_DEF 定义service中的uri响应函数
        virtual void preparePattern();

        void releaseServiceUriHandlers() {
            uri_map_.clear();
        }

        virtual void onServiceStart(const qlibc::QData& config) { active_ = true;}

        virtual void onServiceStop() { active_=false;}

        inline void setClearJedgeCallInfo(bool clear = true) {
            auto_remove_call_info = clear;
        }

        inline bool isActive() {
            return active_;
        }

        //获取Module的出口IP地址
        std::string getModuleHost();
        //获取module的主机出口Port
        int getModuleHostPort();

        //获取当前接入的mgbus节点串号
        auto getLocalMgbusHostSn() -> const std::string& {
            requestMgbusSn();
            return host_sn_;
        }

        //获取当前module的mgbus全地址
        auto getModuleFullMgbusName() -> std::string {
            return operator_.name() + "@" + getLocalMgbusHostSn() + ".local";
        }

        //获取当前接入mgbus节点的mgnet域
        auto getLocalMgbusDomain() -> std::string {
            return getLocalMgbusHostSn() + ".local";
        }

        bool isLocalMgbusEvent(const qlibc::QData& msg) {
            auto mgnet = msg.getString("mgnet");
            return mgnet == getLocalMgbusDomain() || mgnet.empty();
        }
        //重新刷新所有的事件监听(更新远端事件的回调源)
        void rewatchAllWatchers();

    protected:

        void requestMgbusSn();

        bool unImplementedCommand(qlibc::JCArgNode& param);
        //启动时显示版本信息
        void showStartVersion(qlibc::JCArgNode& param);

        void addUriHandler(const std::string &pattern, const ServiceMessageHandler &handler);

        void loadExConfigInfo(const std::string &configFileName);

        bool default_MessageHandler(const std::string &uri, const std::string &src, qlibc::QData &message,
                                    qlibc::QData &response);

        virtual bool handle_Default(qlibc::QData &msg, qlibc::QData *rsp) {
            return false;
        };

        virtual bool _ecb(qlibc::QData &msg, qlibc::QData *rsp);    //事件回调函数
        bool qh(qlibc::QData &msg, qlibc::QData *rsp);      //查询API
        bool qe(qlibc::QData &msg, qlibc::QData *rsp);      //查询事件
        bool ver(qlibc::QData &msg, qlibc::QData *rsp);     //查询版本

        virtual const char *localKey(jedge::CallInfoKeyType type);

        void emtpyWatchers();

        void releaseWatchers();

        void registerUserDefineCommand ( const std::string& cmd, const qlibc::QCmdRunnerHandler& handler, const std::string& helpInfo);

    public:

        virtual void onConfigDataUpdated(const std::string &cfgFileName);

        std::string getCacheServiceFileName(const std::string &relaFn) {
            std::string fn;
            FileUtils::contactFileNames(fn, operator_.getDataCacheRootDir().c_str(), operator_.name().c_str(), name().c_str(), relaFn.c_str(), nullptr);
            return fn;
        }

        std::string getInitServiceFileName(const std::string &relaFn) {
            std::string fn;
            FileUtils::contactFileNames(fn, operator_.getDataInitRootDir().c_str(),  operator_.name().c_str(), name().c_str(), relaFn.c_str(), nullptr);
            return fn;
        }

        //发送service-service消息, 跨mgmodule的消息格式：
        virtual bool postServiceRequest(const std::string &mod, const std::string &uri, qlibc::QData &req, qlibc::QData &rsp, int to_ms = -1);

        inline bool postMgbusServerRequest(const std::string &uri, qlibc::QData &req, qlibc::QData &rsp){
            return postServiceRequest(JEDGE_MGBUS_MODUAL_MGS_SERVER, uri, req, rsp);
        }

        virtual bool postServiceMessage(const std::string &mod, const std::string &uri, qlibc::QData &msg);

        inline bool broadcastMgbusMessage(const std::string &uri, qlibc::QData &msg) {
            return postServiceMessage("#", uri, msg);
        }

        inline bool broadcastMgbusNetMessage(const std::string &mod, const std::string &uri, qlibc::QData &msg) {
            return postServiceMessage(mod+"@#", uri, msg);
        }

        inline bool postMgbusServerMessage(const std::string &uri, qlibc::QData &msg) {
            return postServiceMessage(JEDGE_MGBUS_MODUAL_MGS_SERVER, uri, msg);
        }

        //检验是否已经监听了特定事件?
        bool isEventWatched(const std::string &mod, const std::string &event, const string &cbUri, const std::string &key);

        //回调函数 请求本service的uri,注意,uri不带返回值
        const std::string& watchServiceEvent(const std::string &mod, const std::string &event, const std::string &cbMethod, const std::string &key=JEDGE_MGBUS_EVENT_KEY_DEFAULT);

        //回调函数 请求本service的uri
        const std::string& watchServiceEvent(const std::string &mod, const std::string &event, const MgEventWatcherCallback &callback, const std::string &key=JEDGE_MGBUS_EVENT_KEY_DEFAULT);

        //回调函数 请求本service的默认uri
        const std::string& watchMgbusEvent(const std::string &event, const std::string &module,
                const MgEventWatcherCallback &callback);

        //回调函数 请求本service的默认uri
        const std::string& watchMgbusEvent(const std::string &event, const std::string &module, const std::string &cbMethod);

        //回调函数 请求本service的默认uri
        void removeMgbusWatcher(const std::string& event,
                                const std::string& callback="_ecb", const std::string& key = JEDGE_MGBUS_EVENT_KEY_DEFAULT) {
            removeWatcher(JEDGE_MGBUS_MODUAL_MGS_SERVER, event, callback, key);
        }

        //主动清理watcher
        //创建线程处理：避免在watcher的回调函数中调用removeWatcher，导致死锁
        void removeWatcher(const std::string& mod, const std::string& event,
                           const std::string& callback="_ecb", const std::string& key = JEDGE_MGBUS_EVENT_KEY_DEFAULT);

        void addWatcherIndexPool(int wid, MgEventWatcher &watcher);

        bool isAutoReleasing();

        virtual void printHandlers(Json::Value *re);
        virtual void printEventsDefined(Json::Value *re);
    };

    using QServiceList = std::vector<MgService&>;
    using QPServiceList = std::vector<MgService*>;

    class JE_API MgBusServiceHolder {
    protected:
        qlibc::QSharedObjectHolder<MgService> services_;

    public:
        explicit MgBusServiceHolder() {}

        ~MgBusServiceHolder();
        //service一般不会卸载或删除、且自动释放，service从post中获得数据响应调用、并通过mgbus通道进行返回。
        bool appendLocalService(const std::string& key, MgService* service){
            services_.appendNew(key,service);
            return true;
        };

        std::shared_ptr<MgService> findService(const std::string& key){
            return services_.findObject(key);
        }

        bool containsService(const std::string &key) {
            return services_.existObject(key);
        }

        void clearService();

        void serviceKeyList(QStringList &keyList) {
            services_.getKeySets(keyList, true);
        }

        void invokeOnAllServices(const qlibc::QSharedObjectHolder<MgService>::SharedObjAccessor &accessor) {
            services_.invokeOnAllObject(accessor);
        }
    };


#define defaultSelfRef __self_r
#define prepareSelfBind auto __self_r = getSelfRef()

#define bindUriHandler(uri, handler) \
        addUriHandler(uri, [this,defaultSelfRef](qlibc::QData &__msg, qlibc::QData *__rsp) -> bool { \
            AssertAvailableValue(true);    \
            return handler(__msg, __rsp);\
        })

#define bindUriHandlerR(uri, handler,r) \
        addUriHandler(uri, [this,r](qlibc::QData &__msg, qlibc::QData *__rsp) -> bool { \
            AssertAvailableValue(true);    \
            return handler(__msg, __rsp);\
        })

#define bindHandler(handler) \
        addUriHandler(StringUtils::formatString("/%s/%s",name().c_str(),#handler), [this,defaultSelfRef](qlibc::QData &__msg, qlibc::QData *__rsp) -> bool { \
            AssertAvailableValue(true);    \
            return handler(__msg, __rsp); \
        })

#define bindHandlerR(handler,r) \
        addUriHandler(StringUtils::formatString("/%s/%s",name().c_str(),#handler), [this,r](qlibc::QData &__msg, qlibc::QData *__rsp) -> bool { \
            AssertAvailableValue(true);    \
            return handler(__msg, __rsp); \
        })

#define bindDefault(handler) \
        bindUriHandler(StringUtils::formatString("/%s",name().c_str()), handler);\
        bindUriHandler(StringUtils::formatString("/%s/**",name().c_str()), handler)

#define bindDefaultR(handler,r) \
        bindUriHandler(StringUtils::formatString("/%s",name().c_str()), handler);\
        bindUriHandler(StringUtils::formatString("/%s/**",name().c_str()), handler,r)

#define  DefineWatchAfterActionR(__e, __method,r) \
            DefAction(std::string("after_")+#__e, [this,r] (jedge::MgTriggerWatcher &__w, const std::string& __k, const qlibc::QData &__msg)-> bool { \
                AssertAvailableValue(true);            \
                return __method(__w, __k, __msg); \
            })

#define  DefineWatchAfterAction(__e, __method) \
            DefAction(std::string("after_")+#__e, [this,defaultSelfRef] (jedge::MgTriggerWatcher &__w, const std::string& __k, const qlibc::QData &__msg)-> bool { \
                AssertAvailableValue(true);            \
                return __method(__w, __k, __msg); \
            })

#define  DefineWatchBeforeActionR(__e, __method,r) \
            DefAction(std::string("before_")+#__e, [this,r] (jedge::MgTriggerWatcher &__w, const std::string& __k, const qlibc::QData &__msg)-> bool { \
                AssertAvailableValue(true);            \
                return __method(__w, __k, __msg); \
            })

#define  DefineWatchBeforeAction(__e, __method) \
            DefAction(std::string("before_")+#__e, [this,defaultSelfRef] (jedge::MgTriggerWatcher &__w, const std::string& __k, const qlibc::QData &__msg)-> bool { \
                AssertAvailableValue(true);            \
                return __method(__w, __k, __msg); \
            })

#define AddLocalWatchR(__act,r) \
        watchLocalEvent(#__act, jedge::JEDGE_MGBUS_EVENT_KEY_DEFAULT, [this,r](jedge::MgTriggerWatcher &__w, const std::string& __k, const qlibc::QData &__m)->bool { \
                AssertAvailableValue(true);            \
                return this->__act(__w,__k,__m);                                                                                                                     \
        })

#define AddLocalWatch(__act) \
        watchLocalEvent(#__act, jedge::JEDGE_MGBUS_EVENT_KEY_DEFAULT, [this,defaultSelfRef](jedge::MgTriggerWatcher &__w, const std::string& __k, const qlibc::QData &__m)->bool { \
                AssertAvailableValue(true);            \
                return this->__act(__w,__k,__m);                                                                                                                     \
        })

#define _WatchServiceEventR(__m,__k, __hdlr,r) \
        watchServiceEvent(__m, __k, [this,r]WatcherCallbackLamda(m){ \
                AssertAvailableValue(true);            \
                return this->__hdlr(m);      \
        })

#define _WatchServiceEvent(__m,__k, __hdlr) \
        watchServiceEvent(__m, __k, [this,defaultSelfRef]WatcherCallbackLamda(m){ \
                AssertAvailableValue(true);            \
                return this->__hdlr(m);      \
        })

#define _WatchServiceEventOnEventCallbackR(__m,__k, __hdlr,r) \
        watchServiceEvent(__m, __k, [this,r]WatcherCallbackLamda(m){ \
            AssertAvailableValue(true);       \
            return this->__hdlr(m);      \
        })

#define _WatchServiceEventOnEventCallback(__m,__k, __hdlr) \
        watchServiceEvent(__m, __k, [this,defaultSelfRef]WatcherCallbackLamda(m){ \
            AssertAvailableValue(true);       \
            return this->__hdlr(m);      \
        })

//当目标module下线时、自动清理watcher的key
#define bindServiceEventR(__m,__kl,__hdlr,r) \
        watchMgbusEvent("online", __m,[this,r]WatcherCallbackLamda(___m){ \
            AssertAvailableValue(true);       \
            for(auto& __k:StringUtils::SplitString(__kl,","))           \
                _WatchServiceEvent(__m, __k, __hdlr);                   \
            return true;                    \
        });                                  \
        watchMgbusEvent("offline", __m, [this,r]WatcherCallbackLamda(___m){ \
            AssertAvailableValue(true);       \
            for(auto& __k:StringUtils::SplitString(__kl,","))           \
                removeWatcher(MgEventWatcher::makeWatcherKey(__m, __k)); \
            return true;                        \
        })

//当目标module下线时、自动清理watcher的key
#define bindServiceEvent(__m,__kl,__hdlr) \
        watchMgbusEvent("online", __m,[this,defaultSelfRef]WatcherCallbackLamda(___m){ \
            AssertAvailableValue(true);       \
            for(auto& __k:StringUtils::SplitString(__kl,","))           \
                _WatchServiceEvent(__m, __k, __hdlr);                   \
            return true;                    \
        });                                  \
        watchMgbusEvent("offline", __m, [this,r]WatcherCallbackLamda(___m){ \
            AssertAvailableValue(true);       \
            for(auto& __k:StringUtils::SplitString(__kl,","))           \
                removeWatcher(MgEventWatcher::makeWatcherKey(__m, __k)); \
            return true;                        \
        })

#define DefineWatcherHandler(__hdlr, __w,__k, __m) \
        __hdlr(jedge::MgTriggerWatcher &__w, const std::string& __k, const qlibc::QData &__m)

#define WatcherHandlerLamda(__w,__k, __m) \
        (jedge::MgTriggerWatcher &__w, const std::string& __k, const qlibc::QData &__m)->bool

#define WatcherCallbackLamda(__m) \
        (qlibc::QData& __m)->bool

#define BindServiceCommand(_cmd, _help, _Handler) \
    registerUserDefineCommand(_cmd, [this](unsigned int *retCode, void **d, void* ctx)->bool { \
        GET_CMD_PARAM(args, d);                    \
        return _Handler(*args);              \
    }, _help)

#define ServiceCommandCallback(_r,_d,_ctx)
}

#endif //INC_0_LIBDEVCPP_CPAD_MGSERVICE_H
