//
// Created by Ht on 2021/4/17.
//

#ifndef INC_0_LIBDEVCPP_QEXMGBUSSERVER_H
#define INC_0_LIBDEVCPP_QEXMGBUSSERVER_H

#include <mgbus/QMgbusModule.h>
#include <exlib/http/QASyncHttpServer.h>
#include <exlib/sock/QNodeServer.h>
#include <exlib/http/ECSInvokeService.h>
#include <exlib/sock/MgNodeManagerService.h>

namespace jedge {

    class JE_API MgbusModuleWithHttp : public QMgbusModule {
    public:
        explicit MgbusModuleWithHttp(const qlibc::QData& initConfig, const std::string& modulename)
                : QMgbusModule(initConfig, modulename), mHttpServer(*this), cmdns_client_(threadPool(), timerEngine()) {
            markDataChannel(DATA_CHANNEL_HTTP, mHttpServer);
        };

        ~MgbusModuleWithHttp() override = default;

    protected:
        QASyncHttpServer mHttpServer;
        QCMDnsClient     cmdns_client_;

        void prepareService(const qlibc::QData &config) override {
            //消息转发调试服务，可模拟向自己或其它指定模块发送mgbus消息
#ifdef DEBUG
            DefineMgbusService("@i", ECSInvokeService, config);
#endif
            MgBusHolder::prepareService(config);
        }

    public:
        declareHttpUriHandlers(mHttpServer);

        void doServerShutdown() override {
            mHttpServer.shutdown();
        }

        virtual int defaultHttpPort() = 0;

        bool doServerStart(const qlibc::QData& config) override {
            int http_port = runData_.getInt("http_port", defaultHttpPort());

            if(http_port<1) {
                QErr("Invalid http server port: %d .", http_port);
                return false;
            }

            if(!mHttpServer.start(http_port)){
                QErr("Bind http server on %d failed.", http_port);
                return false;
            }

            //@mg.module.service 标志开头的默认全部转发
            bindMgBusTransfer(mHttpServer);

            return true;
        }
    };

    class JE_API MgbusModuleWithSocket : public QMgbusModule {
    public:
        explicit MgbusModuleWithSocket(const qlibc::QData& initConfig, const std::string& modulename, SocketMode sockType = typeUDP)
                : QMgbusModule(initConfig, modulename, sockType), mSockServer(*this) {
            markDataChannel(DATA_CHANNEL_SOCK, mSockServer);
        };

        ~MgbusModuleWithSocket() override = default;

    protected:
        QNodeServer      mSockServer;

    public:
        void prepareService(const qlibc::QData &config) override {
            //可向指定的node发送消息，消息处理接口，响应来自mgbus或http的的mm请求
            DefineMgbusServiceWithInitFieldObj("mm", MgNodeManagerService, config, mSockServer);
            MgBusHolder::prepareService(config);
        }

        void doServerShutdown() override {
            mSockServer.shutdown();
        }

        virtual int defaultSocketPort()  = 0;

        bool doServerStart(const qlibc::QData& data) override {
            int ms_port = runData_.getInt("sc_port", defaultSocketPort());
            if(ms_port<1){
                QErr("Invalid socket server port: %d .", ms_port);
                return false;
            }

            std::string sockType = runData_.getString("sc_type", "tcp");
            if(!mSockServer.start(runData_, ms_port, sockType=="udp"?typeUDP:typeTCP)){
                QErr("Fail to start socket Server on port : %d.", ms_port);
                return false;
            }
            return true;
        }
    };

    class JE_API MgbusModuleMix : public QMgbusModule {
    protected:
        QASyncHttpServer mHttpServer;
        QNodeServer      mSockServer;

    public:
        declareHttpUriHandlers(mHttpServer);

        explicit MgbusModuleMix(const qlibc::QData& initConfig, const std::string& modulename)
                : QMgbusModule(initConfig, modulename), mHttpServer(*this), mSockServer(*this) {
            markDataChannel(DATA_CHANNEL_SOCK, mSockServer);
            markDataChannel(DATA_CHANNEL_HTTP, mHttpServer);
            //Http的消息推送，该从本地的Socket发起
            mHttpServer.setASyncPostHandler([this](ChannelOperator& opr, qlibc::QData &response)->bool {
                return mSockServer.postRawMessage(response);
            });
        };

        ~MgbusModuleMix() override = default;

        void prepareService(const qlibc::QData &config) override {
            //消息转发调试服务，可模拟向自己或其它指定模块发送mgbus消息
#ifdef DEBUG
            DefineMgbusService("@i", ECSInvokeService, config);
#endif
            //可向指定的node发送消息，消息处理接口，响应来自mgbus或http的的mm请求
            DefineMgbusServiceWithInitFieldObj("mm", MgNodeManagerService, config, mSockServer);
            MgBusHolder::prepareService(config);
        }

        virtual int defaultHttpPort() = 0;

        virtual int defaultSocketPort() = 0;

        void doServerShutdown() override {
            mHttpServer.shutdown();
            mSockServer.shutdown();
        }

        bool doServerStart(const qlibc::QData& config) override {
            int http_port = runData_.getInt("http_port", defaultHttpPort());
            if(http_port<1) {
                QErr("Invalid http server port: %d .", http_port);
                return false;
            }
            if(!mHttpServer.start(http_port)) {
                QErr("Bind http server on %d failed.", http_port);
                return false;
            }
            //@mg.module.service 标志开头的默认全部转发
            bindMgBusTransfer(mHttpServer);

            int ms_port = runData_.getInt("sc_port", defaultSocketPort());
            if(ms_port<1){
                QErr("Invalid socket server port: %d .", ms_port);
                mHttpServer.shutdown(); //停止已启动的http服务器
                return false;
            }

            std::string sockType = runData_.getString("sc_type", "udp");
            if(!mSockServer.start(runData_, ms_port, sockType=="udp"?typeUDP:typeTCP)){
                QErr("Fail to start socket Server on port : %d.", ms_port);
                mHttpServer.shutdown(); //停止已启动的http服务器
                return false;
            }
            return true;
        }
    };


    //MgbusModuleWithSocketClient


    //MgbusModuleWithMqttClient


    //MgbusModuleWithMixClient
}

#endif //INC_0_LIBDEVCPP_QEXMGBUSSERVER_H
