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

#ifndef INC_1_LIBDEVCPP_JAEXTCOMMANDOR_H
#define INC_1_LIBDEVCPP_JAEXTCOMMANDOR_H

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

#include <utility>

namespace qlibc {

    class JAExtCommandor;

    using JAExtCommandHandler = std::function<bool(qlibc::JCArgNode& node)>;
    using JAExtCommandHandlerR = std::shared_ptr<JAExtCommandHandler>;

    using JAExtFuncCommandHandler = std::function<bool(JAExtCommandor& cmdor, qlibc::JCArgNode& node)>;
    using JAExtFuncCommandHandlerR = std::shared_ptr<JAExtFuncCommandHandler>;

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

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

    public:
        jedge::QJAMgServer& server_;
        jedge::QJAMgService& service_;
        std::string target_mod_;

        explicit JAExtCommandor(std::string cmdKey, jedge::QJAMgServer& opr, jedge::QJAMgService& svc) :
            cmd_(std::move(cmdKey)), server_(opr), service_(svc)
            {}
        virtual ~JAExtCommandor() = default;

        virtual void buildCommandHandlers() {}

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

        void showHelpInfo();

        bool handleCommand(qlibc::JCArgNode &node);

        void initHandlers(const std::string& debugModule);

        void appendHandler(const std::string& cmdKey, const JAExtCommandHandler& handler,const std::string& help);
        void appendHandler(const std::string& cmdKey, const JAExtFuncCommandHandler& handler,const std::string& help);
    };

    using JAExtCommandorR = std::shared_ptr<JAExtCommandor>;

#define defineCommandorHandler(_func,_help) \
    appendHandler(#_func, [this](qlibc::JCArgNode& _nd)->bool { \
        return _func(_nd); \
    },_help)

#define defineCommandorFuncHandler(_func,_help) \
    appendHandler(#_func, [](qlibc::JAExtCommandor& _cd, qlibc::JCArgNode& _nd)->bool { \
        return _func(_cd,_nd); \
    },_help)

#define defineCommandorFuncHandlerBy(_cmd,_func,_help) \
    appendHandler(_cmd, [](qlibc::JAExtCommandor& _cd, qlibc::JCArgNode& _nd)->bool { \
        return _func(_cd,_nd); \
    },_help)

#define BindServiceCommandHandlers(_cmd, _help, _handler, _cmdor,_mod) \
            BindServiceCommand(_cmd, _help, _handler);\
            _handler##_cmdor = std::make_shared<jedge::_cmdor>(_cmd,getContextServer(),*this);   \
            _handler##_cmdor->initHandlers(_mod);

#define ImplementCommandHandler(_handler,_cmdor) \
    protected:  std::shared_ptr<jedge::_cmdor> _handler##_cmdor; \
    public:  bool _handler(qlibc::JCArgNode& _p) { \
        if((_handler##_cmdor)!=nullptr && (_handler##_cmdor)->handleCommand(_p)) \
            return true; \
        QWarn("Unhandled command : %s", _p.toJSONString().c_str()); \
        return true; \
    }

}

#endif //INC_1_LIBDEVCPP_JAEXTCOMMANDOR_H
