//
// Created by Ht on 2021/1/17.
//

#ifndef LIBDEVCPP_MGSERVERINTF_H
#define LIBDEVCPP_MGSERVERINTF_H

#include <qlibc/qlibc.h>

namespace jedge {

    class JE_API MgServerIntf {
    private:
        bool mbRunning = false;

    public:
        inline virtual bool start(const qlibc::QData &config) { mbRunning=true; return mbRunning;};
        inline virtual void shutdown() { mbRunning = false;};
        inline bool isRunning()  { return mbRunning; };
    };
    /**
     *  定义一个Runner的类、于jedge服务进行捆绑命令回调方法
     *      并自动定义start/s, stop/p, restart/r命令
     *
     *      此宏需要与 bindServiceRunnerCallbackTable_Begin / bindServiceRunnerCallbackTable_End 一起使用
     *
     *
     *      rcls是自定义Runner的类名称
     *      scls为jedge的服务类
     *      cfgFn为服务的启动配置文件名、需要包含路径
     */
#define DefineServiceRunner(rcls, scls, cfgFn) \
    bindRunner(rcls, scls);\
    DefCmdCallback(rcls##_Start, s, p, rcls, scls) { \
        if (!s.isRunning()) {\
            qlibc::QData d; \
            s.loadInitDataConfig(cfgFn, d);              \
            if(!p.isEmpty()) d.copyData(p);\
            auto mghost=p.getParam(1);                     \
            if(!mghost.empty()) d.setString("mg_host",mghost); \
            auto mgport=p.getParamAsInt(2);                     \
            if(mgport>0) d.setInt("mg_port", mgport); \
            QLog("starting with config:\n------\n%s\n====[.]", d.toJSONString(true).c_str());\
            if(s.start(d)) \
            QLog("%s start ok.", #rcls);\
        } else { QLog("%s is already running ... ", #rcls);} \
        return true;}\
    DefCmdCallback(rcls##_Stop, s, p, rcls, scls) { \
        if (s.isRunning()) {\
            s.shutdown(); \
            QLog("%s stopped.", #rcls);\
        } else QLog("%s is not running ... ", #rcls);\
        return true;} \
    DefCmdCallback(rcls##_Restart, s, p, rcls, scls ) {\
             rcls##_Stop(s,p);\
             SystemUtil::tryWait(500);\
             rcls##_Start(s,p);\
        return true;}

/**
*  与上一个宏功能及使用条件相同，但允许服务的构造函数带一个参数 obj
*/
#define DefineServiceRunnerWithInitObj(rcls, scls, cfgFn, appName, objcls) \
    bindRunnerWithInitObj(rcls, scls, appName, objcls);\
    DefCmdCallback(rcls##_Start, s, p, rcls, scls) { \
        if (!s.isRunning()) {\
            qlibc::QData d; \
            s.loadInitDataConfig(cfgFn, d); \
            if(!p.isEmpty()) d.copyData(p);\
            auto mghost=p.getParam(1);                     \
            if(!mghost.empty()) d.setString("mg_host",mghost); \
            auto mgport=p.getParamAsInt(2);                     \
            if(mgport>0) d.setInt("mg_port", mgport); \
            QDLog("starting with config:\n\t%s", d.toJSONString(true).c_str());\
            if(s.start(d)) \
            QLog("%s start ok.", #rcls);\
        } else { QLog("%s is already running ... ", #rcls);} \
        return true;}\
    DefCmdCallback(rcls##_Stop, s, p, rcls, scls) { \
        if (s.isRunning()) {\
            s.shutdown(); \
            QLog("%s stopped.", #rcls);\
        } else QLog("%s is not running ... ", #rcls);\
        return true;} \
    DefCmdCallback(rcls##_Restart, s, p, rcls, scls ) {\
        rcls##_Stop(s,p);\
        SystemUtil::tryWait(500);\
        rcls##_Start(s,p);\
        return true;}

        /**
         * 配合 DefineServiceRunner 或 DefineServiceRunnerWithInitObj 使用
         *  必须使用、哪怕不增加自定义的方法。
         */
#define bindServiceRunnerCallbackTable_Begin(rcls)\
    bindCallbackTable_Begin(rcls)\
        RegisterFunctionCommandWithHelp("s,start", rcls##_Start,"start module");\
        RegisterFunctionCommandWithHelp("r,restart", rcls##_Restart,"restart module");\
        RegisterFunctionCommandWithHelp("p,stop", rcls##_Stop, "shutdown module");

    /**
    * 配合  bindServiceRunnerCallbackTable_Begin 使用， 中间添加命令方法回调函数绑定
    */
#define bindServiceRunnerCallbackTable_End(rcls) bindCallbackTable_End(rcls)


    /**
     * 快速定义析构函数
     */
#define ImplServerRelease(cls) \
        ~cls() override {if(isRunning())shutdown();}

}

#endif //LIBDEVCPP_MGSERVERINTF_H
