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

#ifndef INC_1_LIBDEVCPP_QJAGAFFICCONTEXT_H
#define INC_1_LIBDEVCPP_QJAGAFFICCONTEXT_H


#include <exlib/QJAServer.h>
#include <exlib/QJAService.h>
#include "QJAGafflicSite.h"
#include "gao/QGAActionObjects.h"
#include "QGADataPool.h"

namespace jedge {
#if 0 // DEBUG
    static const char* default_site_mod_base_uri = "http://127.0.0.1:8082";
#else
    static const char* default_site_mod_base_uri = "http://139.155.15.33:8080/jedge";
#endif
    using QJAGafficSiteTask = std::function<void(const std::string& k, QJAGafflicSite& o)>;
    class JE_API QJAGafficContext : public QGADataPool {
    protected:
        QJAMgServer &opr_;
        QJAMgService &service_;

        std::unordered_set<std::string>       excluded_sites_;      //扫描到，但是不加载
        std::unordered_set<std::string>       used_http_base_;      //记录已被使用的http/https base地址，不可重入
        qlibc::QPObjectHolder<QJAGafflicSite> sites_;
        qlibc::QPluginManager*                encryptionPluginManager = nullptr;      //插件管理器,针对不同的站点的特殊函数实现,例如:加解密函数。
        std::string                           site_mod_path_;
        std::string                           site_mod_host_base_;
        qlibc::QRTimer                        update_mod_timer;
        std::recursive_mutex                  m_;
        bool inited_ = false;

    public:
        explicit QJAGafficContext(QJAMgServer &server, QJAMgService &service, qlibc::QData& data);

        ~QJAGafficContext() override;

        static QJAGafficContext &getInstance(QJAMgServer &server, jedge::QJAMgService& service);

        static void clearContext();

        void loadDefaultAIoTSites();

        void loadCacheAIoTSites();

        void loadAIoTSite(const std::string& siteName, const std::string& basePath, qlibc::QData& config);

        bool mgbusHandle(QData &req, QData *rsp);

        QJAGafflicSite* findSite(const string &siteKey);

        void listLoadedSites();

        void runOnAllSites(const QJAGafficSiteTask& task);

        void getAvailableSiteMod(QStringList& mods);

        bool setSiteModeHostBase(const std::string &baseHost);

        bool updateSiteModes(QStringList& mods);

        bool removeSiteData(const std::string &siteName);

        bool updateSite(qlibc::QData &req, qlibc::QData *resp);

        string getFirstSiteName();

    protected:
        void reprepareMqttTopics(const qlibc::QData& data) override;

    public:

        void httpRequest(const std::string& uriKey, qlibc::QData& req, qlibc::QData& resp);

        void httpsRequest(const std::string& uri, qlibc::QData& req, qlibc::QData& resp);

        void initContext();

        void releaseContext();

        QGaCypherPluginEntry *findGafficPluginEntry(const string &siteName);

    protected:

        void loadAIoTSiteByPath(const std::string& path);

        void loadCypherPlugins();

        void buildCypherFunctionPools();

        void releaseCypherFunctionPools();

        void removeLocalSiteMod(const std::string &siteName);

        bool downloadSiteMode(const std::string &siteMod);

        bool updateSiteParams(qlibc::QData &siteData, const qlibc::QData &params, const std::string& modName);

        //检查http/https等base地址是否已被使用，如果未使用，则记录它
        bool checkHttpHostFree(const qlibc::QData &params, bool updateAfterCheck = false);

        void clearHttpHostBase(const qlibc::QData &params);

        void saveSiteData(qlibc::QData& cfg, const std::string& siteName, const qlibc::QData& params);

        void downloadSiteCertFile(const std::string &basePath, const std::string &certFileName, const qlibc::QData& params);

        void updateHostSetup(const QData &params);

        bool checkHostChanged(const qlibc::QData &newcfg, const qlibc::QData &orgCfg);
    };
}

#endif //INC_1_LIBDEVCPP_QJAGAFFICCONTEXT_H

