#pragma once

#include <functional>
#include <string>
#include <utility>
#include <vector>

struct PqToolConfig {
    std::string frontInst = "6c2adb324940e19e208d717f4970f2ee";
    std::string frontIp = "192.168.1.68";
    std::string terminalStatus = "[0]";
    std::string monitorStatus = "[1,2]";
    std::string icdFlag = "0";

    std::string webDevice = "http://192.168.1.68:10202/nodeDevice/nodeDeviceList";
    std::string webIcd = "http://192.168.1.68:10202/icd/icdPathList";
    std::string webFiledownload = "http://192.168.1.68:10207/file/download";
    std::string xmlSaveDir = "runtime\\downloaded_xml";

    std::string producer = "TRACE_PRODUCER";
    std::string ipport = "192.168.1.68:9876";
    std::string producerAccessKey = "rmqroot";
    std::string producerSecretKey = "001@#njcnmq";
    std::string topicLOG = "ask_log_Topic";
    std::string tagLOG = "6c2adb324940e19e208d717f4970f2ee";
    std::string keyLOG = "Test_Keys";

    std::string consumer = "TRACE_CONSUMER";
    std::string consumerIpport = "192.168.1.68:9876";
    std::string consumerAccessKey = "rmqroot";
    std::string consumerSecretKey = "001@#njcnmq";
    std::string dataStatTopic = "MQ_INST_1697676490574298_Bm3DLamM%LN_Topic";
    std::string dataRealtimeTopic = "MQ_INST_1697676490574298_Bm3DLamM%Real_Time_Data_Topic";
    std::string dataTopic = "MQ_INST_1697676490574298_Bm3DLamM%LN_Topic";
    std::string dataStatTag = "6c2adb324940e19e208d717f4970f2ee";
    std::string dataStatKey = "Test_Keys";
    std::string dataRealtimeTag = "6c2adb324940e19e208d717f4970f2ee";
    std::string dataRealtimeKey = "Test_Keys";
    std::string dataTag = "6c2adb324940e19e208d717f4970f2ee";
    std::string dataKey = "Test_Keys";
    std::string traceTopic = "Trace_Topic";
    std::string traceTag = "6c2adb324940e19e208d717f4970f2ee";
    std::string traceKey = "Test_Key";

    std::string xmlPath;
    std::string jsonDataPath = "runtime\\json\\jsondata.txt";
    std::vector<std::string> jsonDataPaths;
    std::vector<std::string> originPaths;
    std::string outputPath = "runtime\\final_sorted.xls";
    std::string traceRootDir = "runtime\\trace_data";
};

struct PqLedgerMonitor {
    std::string id;
    std::string name;
    std::string lineNo;
    std::string voltageLevel;
    std::string connectType;
    std::string status;
    std::vector<std::pair<std::string, std::string>> fields;
};

struct PqLedgerDevice {
    std::string id;
    std::string name;
    std::string ip;
    std::string status;
    std::string devType;
    std::string devKey;
    std::string orgName;
    std::string stationName;
    std::string subName;
    std::string manufacturer;
    std::string port;
    std::string series;
    std::string updateTime;
    std::string processNo;
    std::string maxProcessNum;
    std::string xmlPath;
    std::vector<std::pair<std::string, std::string>> fields;
    std::vector<PqLedgerMonitor> monitors;
};

using PqLogFn = std::function<void(const std::string&)>;

struct PqMqEvent {
    std::string kind;
    std::string title;
    std::string body;
    std::string path;
};

using PqMqEventFn = std::function<void(const PqMqEvent&)>;

PqToolConfig pqDefaultConfig();
bool pqFetchLedgerAndIcd(const PqToolConfig& cfg,
                         std::vector<PqLedgerDevice>& devices,
                         std::string& firstXmlPath,
                         PqLogFn log);
bool pqInitializeMq(const PqToolConfig& cfg, PqLogFn log, PqMqEventFn event = {});
std::string pqBuildTracePayload(const PqToolConfig& cfg,
                                const PqLedgerDevice& device,
                                const PqLedgerMonitor& monitor,
                                const std::string& frontType);
bool pqSendTraceRequest(const PqToolConfig& cfg,
                        const PqLedgerDevice& device,
                        const PqLedgerMonitor& monitor,
                        const std::string& frontType,
                        PqLogFn log,
                        PqMqEventFn event = {});
void pqClearTraceRecords(const PqToolConfig& cfg,
                         const PqLedgerDevice& device,
                         const PqLedgerMonitor& monitor);
std::string pqTraceDirectoryFor(const PqToolConfig& cfg,
                                const PqLedgerDevice& device,
                                const PqLedgerMonitor& monitor);
std::string pqFindDeviceXmlPath(const PqToolConfig& cfg, const PqLedgerDevice& device);

bool pqRunParser(const std::string& xmlPath,
                 const std::string& jsonPath,
                 const std::vector<std::string>& originPaths,
                 const std::string& outPath,
                 std::string* err,
                 const std::string& frontType = "");
bool pqRunParser(const std::string& xmlPath,
                 const std::vector<std::string>& jsonPaths,
                 const std::vector<std::string>& originPaths,
                 const std::string& outPath,
                 std::string* err,
                 const std::string& frontType = "");

int runPqGuiApp();
