//
// Created by Ht on 2021/11/29.
//

#ifndef INC_0_LIBDEVCPP_QJAEXOBJECTS_H
#define INC_0_LIBDEVCPP_QJAEXOBJECTS_H

#include <jadom2/JAIndexedDom.h>
#include <exlib/sock/QNodeServer.h>
#include <exlib/sock/QSockClient.h>
#include <exlib/http/QHttpSSLClient.h>
#include <exlib/http/QASyncHttpServer.h>
#include <exlib/QMqttClient.h>
#include <mgbus/QMgbusModule.h>
#include <exlib/QJAService.h>
#include <exlib/sock/QNodeClient.h>
#include <exlib/QJAMgUtils.h>

namespace jedge {

    static const char* sval_cls_name_mqtt_client = "mqttClient";
    static const char* sval_cls_name_http_client = "httpClient";
    static const char* sval_cls_name_https_client = "httpSSLClient";
    static const char* sval_cls_name_socket_client = "socketClient";
    static const char* sval_cls_name_http_server = "httpServer";
    static const char* sval_cls_name_socket_server = "socketServer";

    class JAHttpSSLClient : public ja::JAObject ,
                            public UriHandlerHolder {
    protected:
        jedge::QHttpSSLClient*  mClient;

    public:
        explicit JAHttpSSLClient(ja::JAContext& ctx, const qlibc::QData &data):
                JAObject(ctx, data, sval_cls_name_https_client),
                UriHandlerHolder(dynamic_cast<ChannelOperator&>(ctx)) {
        }

        ~JAHttpSSLClient() override;

        jedge::QHttpSSLClient* getClient() {
            return mClient;
        }

        //obj.handler /abc/uri ja_block
        bool handler(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //httpClient.post 'https://192.168.1.193:8080/sbrbusy/' $${result} ${msg} 3000(timeout)
        bool post(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //httpClient.async_post 'https://192.168.1.193:8080/sbrbusy/' ${msg} 3000(timeout)
        bool aspost(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //httpClient.get 'https://192.168.1.193:8080/sbrbusy/' $${result} ${msg} 3000(timeout)
        bool get(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //httpClient.file 'https://192.168.1.193:8080/juras/' localPath(<data-cache-dir>/http/<localPath>
        bool file(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //${@httpClient.req:https://192.168.1.193:8080/juras/panel/check,${msg},3000(timeout),k=v,k2=v2,...}
        bool funcPost(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //${@httpClient.get:https://192.168.1.193:8080/juras/panel/check,k=v,k2=v2,...}
        bool funcGet(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);
    };

    class JAHttpClient : public ja::JAObject ,
                         public UriHandlerHolder {
    protected:
        jedge::QHttpClient*  mClient;

    public:
        explicit JAHttpClient(ja::JAContext& ctx, const qlibc::QData &data);

        ~JAHttpClient() override;

        jedge::QHttpClient* getClient() {
            return mClient;
        }

        //obj.handler /abc/uri ja_block
        bool handler(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //httpClient.post 'http://192.168.1.193:8080/sbrbusy/' $${result} ${msg} 3000(timeout)
        bool post(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //httpClient.async_post 'http://192.168.1.193:8080/sbrbusy/' ${msg} 3000(timeout)
        bool aspost(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //httpClient.get 'http://192.168.1.193:8080/sbrbusy/' $${result} ${msg} 3000(timeout)
        bool get(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //httpClient.file 'http://192.168.1.193:8080/juras/' localPat h(<data-cache-dir>/http/<localPath>
        bool file(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //${@httpClient.req:http://192.168.1.193:8080/juras/panel/check,${msg},3000(timeout),k=v,k2=v2,...}
        bool funcPost(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //${@httpClient.get:http://192.168.1.193:8080/juras/panel/check,k=v,k2=v2,...}
        bool funcGet(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);
    };

    class JAMqttClient : public ja::JAObject ,
                         public UriHandlerHolder {
    protected:
        jedge::QMqttClient*         mqttClient = nullptr;
        jedge::QMqttMessageDeliver* deliver = nullptr;
        std::string                 default_post_topic_;
    public:
        explicit JAMqttClient(ja::JAContext& ctx, const qlibc::QData &data);

        ~JAMqttClient() override;

        jedge::QMqttClient* getClient() {
            return mqttClient;
        }

        //connect host clientid --port <port> --username uid --password pid
        bool connect(qlibc::JCArgNode &param, qlibc::QData *result);

        bool disconnect(qlibc::JCArgNode &param, qlibc::QData *result);

        bool isConnected(qlibc::JCArgNode &param, qlibc::QData *result);

        // subscribe topic
        bool subscribe(qlibc::JCArgNode &param, qlibc::QData *result);

        // unsubscribe topic
        bool unsubscribe(qlibc::JCArgNode &param, qlibc::QData *result);

        // publish topic  ${message} [qos] --key value ...
        bool publish(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //  publish uri $${result} ${message}  --key value ...
        bool publishReq(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        bool returnTopic(qlibc::JCArgNode &param, qlibc::QData *result);

        //obj.handler /abc/uri ja_block
        bool handler(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);


        //DirectCall
        bool directPublish(const std::string& topic, const std::string& content);
        bool directSubscribe(const std::string& topic);
        bool directUnsubscribe(const std::string& topic);
    };


    class JASocketClient : public ja::JAObject {
    protected:
        jedge::QSockClient *mClient = nullptr;
        bool keep_:1;
        bool login_:1;

    public:
        explicit JASocketClient(ja::JAContext& ctx, const qlibc::QData &data);

        ~JASocketClient() override;

        jedge::QSockClient* getClient() {
            return mClient;
        }

        //sclt.connect 192.168.1.30 6013 tcp --keep
        bool connect(qlibc::JCArgNode &param, qlibc::QData *result);

        //client.handler /usi/bbb  ja_block
        bool handler(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //client.req uri $${result} ${msg} to params...
        bool req(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //client.msg uri ${msg} params...
        bool msg(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        bool login(qlibc::JCArgNode &param, qlibc::QData *result);

        bool close(qlibc::JCArgNode &param, qlibc::QData *result);

        bool isActive();

        bool isLogin();
    };

    class JASocketServer : public ja::JAObject {
    protected:
        jedge::QNodeServer*      mSockServer = nullptr;

    public:
        explicit JASocketServer(ja::JAContext& ctx, const qlibc::QData &data);

        ~JASocketServer() override;

        //
        bool start(qlibc::JCArgNode &param, qlibc::QData *result);

        bool shutdown(qlibc::JCArgNode &param, qlibc::QData *result);

        //clientMsg clientId ${msg} --key value
        bool clientMsg(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //getClientList $${resp}
        bool getClientList(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //clientReq clientId uri $${resp} ${msg} --key value
        bool clientReq(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //添加一个uri的handler, param的第一个参数微返回对象
        //obj.handler /uri/uri  block / current:api
        bool handler(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        bool isActive();

        jedge::QNodeServer* getServer();
    };

    class JAHttpServer : public ja::JAObject {
    protected:
        jedge::QASyncHttpServer*      mHttpServer = nullptr;

    public:
        explicit JAHttpServer(ja::JAContext& ctx,const qlibc::QData &data);

        ~JAHttpServer() override;

        //添加一个uri的handler, param的第一个参数微返回对象
        //obj.handler /uri/uri  script/file:entry  [channel(default:msg)] entry
        bool handler(ja::JAStack& s, qlibc::JCArgNode &param, qlibc::QData *result);

        //添加start
        //obj.start 30000 <subnet>
        bool start(qlibc::JCArgNode &param, qlibc::QData *result);

        //添加shutdown
        //obj.shutdown
        bool shutdown(qlibc::JCArgNode &param, qlibc::QData *result);

        bool isActive();

        jedge::QASyncHttpServer* getServer();

        //缓存一个可访问的文件
        //obj.cacheFile <filePath>
        bool cacheFile(ja::JAStack &s, qlibc::JCArgNode &param, QData *result);

        //设置http服务的基础文件目录
        //obj.setBase <filePath>
        bool setWWWBase(ja::JAStack &s, qlibc::JCArgNode &param, QData *result);

    };

    class JE_API QJAExObjectUtils {
    public:
        static void loadExObjects(QJAMgServer& server, ja::JARClassObject &cls);
    };
}


#endif //INC_0_LIBDEVCPP_QJAEXOBJECTS_H
