#ifndef VIDESDATA_H
#define VIDESDATA_H

#include "XNetSDKDefine.h"
#include<QString>
#include <QProcess>
#include <QDate>
#include <QProcess>
#include <QRegularExpression>
#include <QFile>
#include <QTextStream>
#include <QByteArray> 
#include <QNetworkInterface>
#include <iostream>
#include <cstdio>
#include <string>
#include <sstream>
#include <list>
namespace vides_data{
constexpr const char *HEADER_TYPE_KAY="Content-Type";
constexpr const char *HEADER_TYPE_VALUE="application/json";
constexpr const char *PROFLIE_TEST= "test";
constexpr const char *PROFLIE_DEV= "dev";

struct response
{
    int code;
    void* data;
    QString msg;
    response() {}
};

struct requestCameraInfo{
    
    QString ip_addr;
    QString firmware_version;
    QString sSn;
    requestCameraInfo() {}
};

struct requestDeviceStatus
{
    QString sSn;
    int8_t type;
    int8_t status;
    QString ip_addr;
    QString firmware_version;
    std::list<requestCameraInfo>camera_info_list;
    requestDeviceStatus() {}
};
struct responseStsCredentials{
    QString access_key_id;
    QString access_key_secret;
    QString bucket;
    QString endpoint;
    QString expiration;
    QString security_token;
};
struct responseGb28181 {
    QString sip_ip;
    int sip_port;
    QString serial;
    QString realm;
    QString username;
    QString password;
    int register_validity;
    int heartbeat_interval;
    QString device_id;
    QString channel_id;
};
struct responseArea {
    float bottom_right_corner_x;
    float bottom_right_corner_y;
    float bottom_left_corner_x;
    float bottom_left_corner_y;
    
    float top_left_corner_x;
    float top_left_corner_y;
    float top_right_corner_x;
    float top_right_corner_y;
};
struct responseDeviceStatus
{
    QString sSn;
    int8_t type;
    int8_t merchant_id;
    bool is_reboot;
    std::list<responseArea>areas;
    responseDeviceStatus() : is_reboot(false) {}
};
struct responseDeviceData{
    int algorithm ;
    std::list<responseDeviceStatus> list;
    responseStsCredentials sts_credentials;
};

struct localDeviceStatus
{
    QString sSn;
    int8_t type;
    int8_t merchant_id;
    SXSDK_IPAddress HostIP;
    int HttpPort;
    int TCPPort;
    int ChannelNum;
    QString UserName;
    QString password;
    localDeviceStatus() {}
};
struct localDevice
{
    QString sSn;
    QString reachableIp;
    bool isMask;
    int nDevPort;
    int TCPPort;
    int ChannelNum;
    QString UserName;
    QString password;
    localDevice() {}
};

struct requestFaceReconition
{
    QString id;
    QByteArray  img;
    QString sn;
    qint64 time;
    responseArea area;
    requestFaceReconition() {}
};

struct faceRecognitionResult
{
    QString id;
    uint32_t x;
    uint32_t y;
    uint32_t width;
    uint32_t height;
    faceRecognitionResult() {}
};
struct responseFaceReconition
{
    QString id;
    QString  img;
    responseFaceReconition() {}
};
struct ParkingArea
{
    float topLeftCornerX;
    float topLeftCornerY;
    float bottomLeftCornerX;
    float bottomLeftCornerY;
    float bottomRightCornerX;
    float bottomRightCornerY;
    float topRightCornerX;
    float topRightCornerY;
    ParkingArea() {}
};
struct LicensePlate
{
    ParkingArea areaLocation;
    QString new_plate;
    QString new_color;
    QByteArray  img;
    qint64 time;
    ParkingArea recognition;//识别区域
    float text_confidence;
    LicensePlate() {}
};

struct requestLicensePlate
{  
    QString sn;
    std::list<LicensePlate> plates;
    requestLicensePlate() {}
};

struct cameraParameters
{
    QString sDevId;
    int nDevPort;
    QString sUserName;
    QString sPassword;
    int channel;
    QString httpUrl;
    QString sSn;
    QString rtspUrl;
    QString rtmpUrl;
    cameraParameters() {}
};
struct NetWorkNetCommon {
    char* GateWay;        // 网关IP
    char* HostIP;         // 主机IP
    char* HostName;       // 主机名
    int HttpPort;           // HTTP服务端口
    char* MAC;            // MAC地址
    int MaxBps;             // 限定码流值
    char* MonMode;        // 监视协议 {"TCP","UDP","MCAST",…}
    int SSLPort;            // SSL侦听端口
    char* Submask;        // 子网掩码
    int TCPMaxConn;         // 最大连接数
    int TCPPort;            // TCP侦听端口
    char* TransferPlan;   // 传输策略"AutoAdapt":自适应, "Quality":质量优先, "Fluency":流量优先，"Transmission":网传优先
    int UDPPort;            // UDP侦听端口
    bool UseHSDownLoad;     // 是否启用高速录像下载
};


struct responseRecognitionData
{
    int id;
    qint64 inTime;
    qint64 outTime;
    int recognitionType;
    QString sn;
};

struct MainFormat {
    bool AudioEnable;
    int BitRate;
    QString BitRateControl;
    QString Compression;
    int FPS;
    int GOP;
    int Quality;
    QString Resolution;
    int VirtualGOP;
    bool VideoEnable;
    quint64 updateAt;
};

struct ExtraFormat {
    bool AudioEnable;
    int BitRate;
    QString BitRateControl;
    QString Compression;
    int FPS;
    int GOP;
    int Quality;
    QString Resolution;
    int VirtualGOP;
    bool VideoEnable;
    quint64 updateAt;
    
};

struct TimerSettings {
    int deleteLogFileTimer;
    int devicePermissionSynTimer;
    quint64 updateAt;
};
struct Camera {
    int devSnapSynTimer;
    int imageSave;
    QString password;
    QString username;
    float heightReference;
    quint64 updateAt;
};
struct FaceConfig {
    bool isOn;
    int faceNumbers;
    float confidence;
    int faceLen;
    quint64 updateAt;
};

struct LicensePlateConfig {
    bool isOn;
    float carConfidenceMax;
    float carConfidenceMin;
    int licensePlateLen;
    quint64 updateAt;
    int maxNum;                                    ///< 识别最大数量
    bool useHalf;                                  ///< 是否使用半精度推理模式
    float boxConfThreshold;                        ///< 检测框阈值
    float nmsThreshold;                             ///< 非极大值抑制阈值
    float recConfidenceThreshold;                   ///< 识别置信度阈值
    bool isHigh;
};


struct UniformConfig {
    bool isOn;
    int uniformColor;
    int humanDetectionLen;
    float carShapeConfidence;
    quint64 updateAt;
    
};
struct HumanConfig{
    bool isOn;
    uint64 faceFrequency;
    quint64 updateAt;
};

struct MqttConfig {
    QString address;
    QString clientId;
    int qos;
    quint64 timeout;
    QString topic;
    QString username;
    QString password;
    quint64 updateAt;
};

struct responseConfig {
    MainFormat mainFormat;
    ExtraFormat extraFormat;
    TimerSettings timerSettings;
    FaceConfig faceConfig;
    LicensePlateConfig licensePlateConfig;
    UniformConfig uniformConfig;
    Camera camera;
    MqttConfig mqttConfig;
    
    HumanConfig humanConfig;
};

struct responseMqttData{
    uint8_t msg_type;
    QString sn;
    QString uniq;
    QString msg_body;
};

struct requestMqttData{
    QString msg;
    int  code;
    QString uniq;
};
struct DetectionParams {
    int newHumanDetectionLen;
    int newLicensePlateLen;
    int newFaceLen;
    QString modelPaths;
    float humanCarShapeConfidence;
    int uniformColor;
    std::map<QString, QString> faceMaps;
    int numberFaces;
    float faceConfidence;
    __uint8_t algorithmPermissions;
    bool isHigh;
    int maxNum;                                ///< 识别最大数量
    bool useHalf;                              ///< 是否使用半精度推理模式
    float boxConfThreshold;                    ///< 检测框阈值
    float nmsThreshold;                       ///< 非极大值抑制阈值
    float recConfidenceThreshold;             ///< 识别置信度阈值
};

inline bool isVirtualMachine()
{
    QString dmiPath;
    
#ifdef Q_OS_WIN
    dmiPath = "HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System";
#else
    dmiPath = "/sys/devices/virtual/dmi/id/";
#endif
    
    QFile file(dmiPath);
    return file.exists();
}
inline QString getDefaultGateway() {
    QProcess process;
    QString gateway;
    // 根据操作系统的不同选择不同的命令
#ifdef Q_OS_WIN
    QString command = "ipconfig";
    QStringList arguments;
    arguments << "/all";
#elif defined(Q_OS_LINUX)
    QString command = "ip";
    QStringList arguments;
    arguments << "route" << "show" << "default";
#elif defined(Q_OS_MAC)
    QString command = "netstat";
    QStringList arguments;
    arguments << "-nr";
#endif
    
    process.start(command, arguments);
    
    // 等待进程结束
    process.waitForFinished();
    
    // 读取并处理输出
    QString output(process.readAllStandardOutput());
    
#ifdef Q_OS_WIN
    // 使用正则表达式来查找默认网关
    QRegExp rx("Default Gateway[ .]*: (.+?)(\r\n|\n)");
    if (rx.indexIn(output) != -1) {
        gateway = rx.cap(1).trimmed();
    }
#elif defined(Q_OS_LINUX) || defined(Q_OS_MAC)
    // 对于Linux和Mac，分行并查找包含default字样的行
    QStringList lines = output.split('\n');
    QRegularExpression rx("^default via (\\S+)");
    foreach (const QString &line, lines) {
        QRegularExpressionMatch match = rx.match(line);
        if (match.hasMatch()) {
            gateway = match.captured(1);
            break;
        }
    }
    
#endif
    return gateway;
}

inline void convertQStringToSXSDK_IPAddress(const QString& ipString, SXSDK_IPAddress& hostIP) {
    QHostAddress address(ipString);
    quint32 ip = address.toIPv4Address();

    hostIP.c[0] = (ip >> 24) & 0xFF;
    hostIP.c[1] = (ip >> 16) & 0xFF;
    hostIP.c[2] = (ip >> 8) & 0xFF;
    hostIP.c[3] = ip & 0xFF;
}
inline bool isInSameSubnet(const QString &ip1, const QString &ip2, const QString &mask)
{
    QHostAddress address1(ip1);
    QHostAddress address2(ip2);
    QHostAddress subnetMask(mask);

    // 将IP地址和子网掩码从QHostAddress转换成quint32形式
    quint32 addr1 = address1.toIPv4Address();
    quint32 addr2 = address2.toIPv4Address();
    quint32 maskAddr = subnetMask.toIPv4Address();

    // 进行AND操作
    quint32 result1 = addr1 & maskAddr;
    quint32 result2 = addr2 & maskAddr;

    // 比较结果
    return result1 == result2;
}
inline bool GetNetworkInfoByQNetworkInterface(QString &mac, QString &subnetMask, QString &gateway) {
    QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
    foreach (QNetworkInterface interface, interfaces) {
        if (interface.flags().testFlag(QNetworkInterface::IsUp) &&
                interface.flags().testFlag(QNetworkInterface::IsRunning) &&
                !interface.flags().testFlag(QNetworkInterface::IsLoopBack)) {
            mac = interface.hardwareAddress();

            QList<QNetworkAddressEntry> addressEntries = interface.addressEntries();
            foreach (QNetworkAddressEntry entry, addressEntries) {
                if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) {
                    subnetMask = entry.netmask().toString();

                    // 获取网关地址
                    QProcess process;
                    process.start("sudo", QStringList() << "/sbin/ip" << "route");
                    if (!process.waitForStarted()) {
                        qInfo() << "Failed to start 'ip route' process.";
                        continue;
                    }

                    if (!process.waitForFinished()) {
                        process.kill();
                        qInfo() << "Process 'ip route' timed out.";
                        continue;
                    }

                    QString output = process.readAllStandardOutput();
                    QStringList lines = output.split('\n');
                    foreach (QString line, lines) {
                        if (line.startsWith("default via")) {
                            QStringList parts = line.split(QRegExp("\\s+"));
                            if (parts.size() >= 3) {
                                gateway = parts[2];
                                return true;
                            }
                        }
                    }
                }
            }
        }
    }
    return false; // Return false if no suitable interface is found or gateway not found
}

inline bool pingAddress(const QString &address) {
#ifdef Q_OS_WIN
    // Windows 指令 "ping IP -n 1 -w 超时(ms)"
    QString cmdstr = QString("ping %1 -n 1 -w %2")
            .arg(address).arg(1000);
#else
    // Linux 指令 "ping -c 1 IP"
    QString cmdstr = QString("ping -c 1 %1")
            .arg(address);
#endif

    QProcess cmd;
    cmd.start(cmdstr);
    cmd.waitForReadyRead(1000);
    cmd.waitForFinished(1000);

    QString res = QString::fromLocal8Bit(cmd.readAll());
    qInfo() << res;

#ifdef Q_OS_WIN
    if (res.indexOf("TTL") == -1)
#else
    if (!res.contains("1 packets transmitted, 1 received"))
#endif
    {
        qInfo() << address << QString::fromLocal8Bit("ping不通");
        return false;
    }
    else
    {
        qInfo() << address << QString::fromLocal8Bit("ping通");
        return true;
    }
}

inline QString findReachableIp() {
    QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
    for (const QHostAddress &address : ipAddressesList) {
        if (address.protocol() == QAbstractSocket::IPv4Protocol && !address.isLoopback()) {
            QString ipAddress = address.toString();
            QString currentSubnet = ipAddress.left(ipAddress.lastIndexOf('.') + 1); // 返回子网部分

            for (int i = 254; i >= 1; --i) { // 从 254 开始递减
                QString ip = currentSubnet + QString::number(i);
                qInfo() << "Found findReachableIp IP:" << ip;
                if (!pingAddress(ip)) {
                    qInfo() << "ping 不通的ip:" << ip;
                    return ip;
                }
            }
        }
    }
    return QString(); // 如果没有找到可用的 IP 地址，则返回空字符串
}

inline int GetCpuIdByAsm_arm(char* cpu_id)
{
    FILE *fp = fopen("/proc/cpuinfo", "r");
    if(nullptr == fp)
    {
        qInfo()<<"failed to open cpuinfo";
        return -1;
    }
    
    char cpuSerial[100] = {0};
    
    while(!feof(fp))
    {
        memset(cpuSerial, 0, sizeof(cpuSerial));
        fgets(cpuSerial, sizeof(cpuSerial) - 1, fp); // leave out \n
        
        char* pch = strstr(cpuSerial,"Serial");
        if (pch)
        {
            char* pch2 = strchr(cpuSerial, ':');
            if (pch2)
            {
                memmove(cpu_id, pch2 + 2, strlen(cpuSerial));
                
                break;
            }
            else
            {
                fclose(fp);
                return -1;
            }
        }
    }
    fclose(fp);
    
    return 0;
}

inline QString getCpuSerialNumber() {
    QFile file("/proc/cpuinfo");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qInfo() << "无法打开 /proc/cpuinfo 文件";
        return QString();
    }
    QTextStream in(&file);
    QString line;
    while (!in.atEnd()) {
        line = in.readLine();
        if (line.startsWith("Serial")) {
            QStringList parts = line.split(":");
            if (parts.size() > 1) {
                QString serial = parts.at(1).trimmed();
                return serial;
            }
        }
    }
    return QString();
}
}


#endif // VIDESDATA_H
