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

#ifndef IOT_EDGE_VDALNEW_QVDALDEVICEPORT_H
#define IOT_EDGE_VDALNEW_QVDALDEVICEPORT_H

#include "src/vdao/QGAPortPool.h"
#include "QVDAOUtil.h"
#include "src/vdal/SerialHolder.h"
#include "src/plugin/QGaSerialRebufferPluginEntry.h"

namespace jedge {

    static const char* gao_action_type_serial = "serial";

    class JE_API QVdalDevicePort :
            public qlibc::JARemoteCommandor,
            public QGAPortPool {
    protected:
        QLeveledMergeQueueR  merge_queue_ = nullptr;
        std::shared_ptr<SerialHolder>   default_channel_ = nullptr;
        QGaSerialRebufferPluginEntryR   serial_rebuffer_plugin_entry_ = nullptr;
        QPObjectHolder<Json::Value>*    dynamicEncoders_ = nullptr;
        QPObjectHolder<Json::Value>*    dynamicDecoders_ = nullptr;

    public:
        explicit QVdalDevicePort(QJAMgServer &server, QJAMgService &service, qlibc::QData& config,
                                 const std::string& name, std::string basePath);

        ~QVdalDevicePort() override;

        inline bool controlDeviceAvailable() {
            return default_channel_!= nullptr && default_channel_->controlDeviceAvailable();
        }


        void buildPoolData() override;

        void clearSiteData() override;

        //需要进行变量处理
        std::string showPoolBriefs() const;

        void setupDeviceChannel();

        bool openSerial(const std::string &serialName, const string &serialType, const std::string& upJedp, const std::string& downJedp);

        void setupVdalExtGaoFuncs();

        bool handleMgbusControlMessage(QData &data, QData *pData);

        bool handleSerialMessage(QData &data);

        void validateVar(std::string &ret, const std::string &var);

        void serialPush(QByte *buff, size_t len);

        void handleLocalDebugCommand(const std::string &target, const std::string &cmd, qlibc::JCArgNode &node);
        bool handleRemoteSerialDebugCommand(const std::string &cmd, QData &req, QData *resp);
        bool handleDebuggerCommand(const std::string &cmd, QData &req, QData *resp);

        void listJedpItems(const std::string& grepKey, Json::Value* logs = nullptr, bool isEncoder = false);

        void setupDefaultGaoFuncs() override;

        inline std::shared_ptr<SerialHolder>& getDefaultSerialChannel() {
            return default_channel_;
        }

        void handleMogaControlMessage(qlibc::QData &req, qlibc::QData *response) {
            if(default_channel_!=nullptr){
                default_channel_->handleMogaCtrlResponse(req);
            }
        }
        void handleMogaConfigMessage(qlibc::QData &req, qlibc::QData *response) {
            if(default_channel_!=nullptr){
                default_channel_->handleMogaConfigResponse(req);
            }
        }
    protected:

        void onFunctionFieldDefine(const std::string &pathKey, const string &funcKey, Json::Value &def, const std::string &tmplName) override;

        bool handleExTypeVar(Json::Value &ret, const string &type, const string &varKey) override;

        void setupSerial();


        void clearSerial();

        void onDataActionItemBuilt(QGaDataAction *action) override;

        void onGaoActionObjectBuilt(const string &gaoPath, QGaDataAction *action) override;

        void buildInitExtJedpCoders();

        void buildCommandHandlers() override;

        bool device_devList(const std::string& cmd, qlibc::QData& req, qlibc::QData* resp);
        bool device_checkDevice(const std::string& cmd, qlibc::QData& req, qlibc::QData* resp);
        bool device_run(const std::string& cmd, qlibc::QData& req, qlibc::QData* resp);
        bool device_step(const std::string& cmd, qlibc::QData& req, qlibc::QData* resp);
        bool device_next(const std::string& cmd, qlibc::QData& req, qlibc::QData* resp);
        bool device_go(const std::string& cmd, qlibc::QData& req, qlibc::QData* resp);
        bool device_cancel(const std::string& cmd, qlibc::QData& req, qlibc::QData* resp);

        void handleExtJedpCoders(bool isEncoder, Json::Value& jedpDef, const std::string &templName = "");
    };

    using QVdalDevicePortR = shared_ptr<QVdalDevicePort>;

}
#endif //IOT_EDGE_VDALNEW_QVDALDEVICEPORT_H
