//
// Created by Ht on 2022/8/27.
//

#ifndef INC_1_LIBDEVCPP_QHTTPSSLCLIENT_H
#define INC_1_LIBDEVCPP_QHTTPSSLCLIENT_H

#include "QHttpClient.h"


namespace jedge {
    using HttpsASyncCallback = JE_API std::function<bool(const std::shared_ptr<httplib::SSLClient>& fromClient, const string &uri, qlibc::QData &message)>;
    using HttpsClientR = std::shared_ptr<httplib::SSLClient>;

    class JE_API QHttpSSLClient :
        public MgDataChannel,
        public qlibc::QObjectEventHolder {

    protected:
        qlibc::QSharedObjectHolder<httplib::SSLClient> ssl_clients_;
        std::unordered_map<std::string , std::string>  prefixs_;

        unsigned long time_out_secs_;           //客户端自动清理时间，默认客户端不清理,0表示永久不清理
        qlibc::QRTimer  timer_check_timeout_ = nullptr;
        bool quit_ = false;

        HttpsASyncCallback *handler_ = nullptr;
        std::recursive_mutex  httpssl_client_mutex_;

    public:
        //ChannelOperator &opr, unsigned long auto_clear = 10 * 60 * 1000
        explicit QHttpSSLClient(ChannelOperator &opr, const std::string& name, unsigned long auto_clear = 10 * 60 * 1000) :
            MgDataChannel(opr, name), time_out_secs_(auto_clear) {
            auto self = getSelfRef();
            timer_check_timeout_ = operator_.timerEngine().repeatRun([this, self] lamdaTimerTask(t,p) {
                if(!available()) return false;
                checkClientTimeout(); return true;
            }, HEART_BEAT_GAP_, HEART_BEAT_GAP_);
        }

        ~QHttpSSLClient() override;

        HttpsClientR addHttpsWebSite(const std::string& name, const std::string& host, const std::string& ca_cert_path, int port=443);

        //未找到时，直接使用默认Client
        HttpsClientR findHttpSSLClient(const std::string& name = "");

        HttpsClientR prepareHost(const std::string& name, const std::string& host, int port, const std::string& cert_path = "");

        void setClientBase(const std::string& hostKey, const std::string& prefix);

        bool checkAddUriPrefix(std::string& uri, const std::string& hostKey);

        bool postSyncHttpRequestByHost(const std::string& name, qlibc::QData& request, qlibc::QData& response);

        bool postSyncHttpRequestByUri(const std::string& uri, qlibc::QData& request, qlibc::QData& response);

        bool postASyncHttpRequestByUri(const std::string& uri, qlibc::QData& request);

        bool postRawMessage(qlibc::QData &message) override {
            //仅仅是转发，而不一定需要回调。
            return true;
        }

        void clearHttpsClients();

        bool postHttpsRaw(const std::string& httpUri, const std::string& payload, const char* httpContent);

    protected:

        virtual void handleASyncHttpResponse(const HttpsClientR& fromClient, const string &uri, qlibc::QData &message) const;

        bool doPostHttpRequest(const HttpsClientR& client, const std::string& uri, const qlibc::QData &request, qlibc::QData &response) const;

        bool doPostAsyncHttpRequest(const HttpsClientR& client, qlibc::QData &request) const;

        void checkClientTimeout();
    };
}
#endif //INC_1_LIBDEVCPP_QHTTPSSLCLIENT_H
