//
// Created by Ht on 2022/10/29.
//

#ifndef INC_1_LIBDEVCPP_JARemoteCommandor_H
#define INC_1_LIBDEVCPP_JARemoteCommandor_H

#include <qlibc/qlibc.h>
#include <qlibc/cmd/JCArgNode.h>
#include <exlib/QJAServer.h>
#include <exlib/QJAService.h>

#include <utility>

namespace qlibc {

    class JARemoteCommandor;

    using JARemoteCommandHandler = std::function<bool(const std::string& cmd,
            qlibc::QData& req, qlibc::QData* resp)>;
    using JARemoteCommandHandlerR = std::shared_ptr<JARemoteCommandHandler>;

    using JAExtFuncCommandHandler = std::function<bool(JARemoteCommandor& cmdor, const std::string& cmd,
                                                       qlibc::QData& req, qlibc::QData* resp)>;
    using JAExtFuncCommandHandlerR = std::shared_ptr<JAExtFuncCommandHandler>;

    class JE_API JARemoteCommandHandlerInfo {
    public:
        explicit JARemoteCommandHandlerInfo(const JARemoteCommandHandler& handler, std::string help):
            handler_(std::make_shared<JARemoteCommandHandler>(handler)), help_info_(std::move(help)){}
        explicit JARemoteCommandHandlerInfo(const JAExtFuncCommandHandler& handler, std::string help):
                func_(std::make_shared<JAExtFuncCommandHandler>(handler)), help_info_(std::move(help)){}
        JARemoteCommandHandlerR handler_;
        JAExtFuncCommandHandlerR func_;
        std::string          help_info_;
    };

    using JARemoteCommandHandlerInfoR = std::shared_ptr<JARemoteCommandHandlerInfo>;
    /**
     *  扩展命令实现模块,用于快速生成二级命令实现模块
     *
     *
     */
    class JE_API JARemoteCommandor {
    protected:
        qlibc::QSharedObjectHolder<JARemoteCommandHandlerInfo>  rc_handlers_;
        std::string cmd_;

    public:
        jedge::MgBusHolder& server_;

        explicit JARemoteCommandor(std::string cmdKey, jedge::MgBusHolder& opr) :
            cmd_(std::move(cmdKey)), server_(opr)
            {}
        virtual ~JARemoteCommandor() = default;

        virtual void buildCommandHandlers() {}

        bool accept(const std::string &cmd);

        void showHelpInfo();

        bool handleCommandorCommand(const std::string& cmd, qlibc::QData& req, qlibc::QData* resp);

        void initHandlers();
    };

    using JARemoteCommandorR = std::shared_ptr<JARemoteCommandor>;

#define defineCommandorHandler(_func,_help) \
    rc_handlers_.appendNew(#_func, new qlibc::JARemoteCommandHandlerInfo([this](const std::string& _c, qlibc::QData& _r, qlibc::QData* _p)->bool { \
        return _func(_c,_r,_p); \
    },_help))

#define defineCommandorFuncHandler(_func,_help) \
    rc_handlers_.appendNew(#_func, new qlibc::JARemoteCommandHandlerInfo([]( \
        qlibc::JARemoteCommandor& _cd,const std::string& _c,              \
        qlibc::QData& _r, qlibc::QData* _p)->bool { \
        return _func(_cd,_c,_r,_p); \
    },_help))

#define defineCommandorFuncHandlerBy(_cmd,_func,_help) \
    rc_handlers_.appendNew(_cmd, new qlibc::JARemoteCommandHandlerInfo([](qlibc::JARemoteCommandor& _cd, const std::string& _c, qlibc::QData& _r, qlibc::QData* _p)->bool { \
        return _func(_cd,_c,_r,_p); \
    },_help))

#define OkPRspWithLogs(_r,_l) \
    OkPRsp(_r); if((_r)!= nullptr) {(_r)->put("logs", _l);}
}

#endif //INC_1_LIBDEVCPP_JARemoteCommandor_H
