#include "mainwindow.h"


MainWindow* MainWindow::sp_this=nullptr;

MainWindow::MainWindow()
{
    sp_this=this;
    
    
    
    LogHandler::Get().installMessageHandler();
    QString inifile=QCoreApplication::applicationDirPath()+"/gameras.ini";
    
    qSetting = new QSettings(inifile,QSettings::IniFormat);
    qSetting->setIniCodec(QTextCodec::codecForName("UTF-8"));
    
    modelPaths=qSetting->value("licensePlateRecognition/model_paths").toString();

    QThreadPool* threadPool = QThreadPool::globalInstance();
    
    threadPool->setMaxThreadCount(12);
    
    QString httpurl;
    QString profile=qSetting->value("cloudservice/profile","test").toString();
    if(strcmp(profile.toUtf8().data(),vides_data::PROFLIE_TEST)==0 ){
        httpurl=qSetting->value("cloudservice/test_http").toString();
    }else if(strcmp(profile.toUtf8().data(),vides_data::PROFLIE_DEV)==0 ) {
        httpurl=qSetting->value("cloudservice/dev_http").toString();
    }else{
        httpurl=qSetting->value("cloudservice/pro_http").toString();
    }
    Common & instace= Common::getInstance();
    
    QString serialNumber;
    findLocalSerialNumber(serialNumber);
    bool configFetched = false;
    while (!configFetched) {
        HttpService httpService(httpurl);
        vides_data::response *res = httpService.httpDeviceConfig(serialNumber, config);
        if (res->code != 0) {
            qInfo() << "请求远程商户配置失败，重试中...";
            instace.deleteObj(res);
            QThread::sleep(5); // 等待5秒后重试
        } else {
            instace.deleteObj(res);
            configFetched = true;
        }
    }

    initCommon();
    
    deleteLogFileTimer =new QTimer(this);
    connect(deleteLogFileTimer, &QTimer::timeout, this, &MainWindow::deleteLogFile);
    int deleteLogfileTimer=config.timerSettings.deleteLogFileTimer;
    deleteLogFileTimer->start(deleteLogfileTimer);
    
    
    initFaceFaceRecognition();
    
    
    int uniformColor=config.uniformConfig.uniformColor;
    int humanDetectionLen=config.uniformConfig.humanDetectionLen;
    
    int licensePlateLen=config.licensePlateConfig.licensePlateLen;
    
    int faceLen=config.faceConfig.faceLen;

    float carShapeConfidence=config.uniformConfig.carShapeConfidence;
    
    bool is_high=config.licensePlateConfig.isHigh;

    int maxNum = config.licensePlateConfig.maxNum;
    bool useHalf = config.licensePlateConfig.useHalf;
    float boxThreshold = config.licensePlateConfig.boxConfThreshold;
    float nmsThreshold = config.licensePlateConfig.nmsThreshold;
    float recThreshold = config.licensePlateConfig.recConfidenceThreshold;
    
    AlgorithmTaskManage &algorithmTaskManage= AlgorithmTaskManage::getInstance();
    algorithmTaskManage.initialize(humanDetectionLen,licensePlateLen,faceLen,true,0x00);
    algorithmTaskManage.initHumanDetectionManage(modelPaths,carShapeConfidence,uniformColor);
    algorithmTaskManage.initLicensePlateManage(modelPaths,is_high,maxNum,
                                               useHalf,boxThreshold,nmsThreshold,recThreshold
                                               );
    
    MediaFaceImage* mediaFaceImage= MediaFaceImage::getInstance();
    QString configPath = qSetting->value("devices/sz_config_path").toString();
    QString tempPath = qSetting->value("devices/sz_temp_path").toString();
    
    int sdk_handle= mediaFaceImage->SdkInit(configPath,tempPath);
    if(sdk_handle<0){
        qInfo() << "sdk初始化失败";
        return;
    }
    connect(this, SIGNAL(shutdownSignals(QString,int)), this, SLOT(clearHandle(QString,int)),Qt::QueuedConnection);
    
    
    dePermissionSynTimer=new QTimer(this);
    int dePermissionTimer=config.timerSettings.devicePermissionSynTimer;
    connect(dePermissionSynTimer, &QTimer::timeout, this, [this, httpurl](){
        this->startCamera(httpurl);
    },Qt::QueuedConnection);
    
    this->startCamera(httpurl);
    
    float confidence=config.faceConfig.confidence;
    int faceNumbers=config.faceConfig.faceNumbers;
    
    algorithmTaskManage.initFaceReconitionHandle(localImageMap,faceNumbers,confidence);
    
    // 设置定时器间隔
    dePermissionSynTimer->setInterval(dePermissionTimer);
    
    // 启动定时器
    dePermissionSynTimer->start();
    //dePermissionSynTimer->start(dePermissionTimer);
    
    //vides_data::scanWiFiNetworks();
    
    connect(&server, &QTcpServer::newConnection, this, &MainWindow::handleMatNewConnection);
    
    int port=qSetting->value("localservice/port").toInt();
    
    if (!server.listen(QHostAddress::Any, port)) {
        qInfo() << "Error: Unable to start the server on port 12345";
    } else {
        qInfo() << "Server started, listening on port 12345";
    }
    config.mqttConfig.clientId=serialNumber;
    QString topic = QStringLiteral("/thingshub/%1/device/reply").arg(serialNumber);

    config.mqttConfig.topic=topic;
    this->mqttConfig= config.mqttConfig;
    runOrRebootMqtt(mqttConfig,httpurl,serialNumber);
}
void MainWindow::runOrRebootMqtt(vides_data::MqttConfig &mqtt_config,QString &httpUrl,QString &serialNumber){
    MqttSubscriber* subscriber = MqttSubscriber::getInstance(this);
    subscriber->init(mqtt_config,httpUrl,serialNumber);
    subscriber->start();
}

void MainWindow::divParameterUpdate(vides_data::responseConfig &cloudConfig,QString &httpUrl,QString &serialNumber ){
    bool faceAlgorithm = false, licensePlateAlgorithm = false, uniformAlgorithm = false, timeChange = false;
    AlgorithmTaskManage &algorithmTaskManage= AlgorithmTaskManage::getInstance();

    if(cloudConfig.faceConfig.updateAt!=config.faceConfig.updateAt){
        config.faceConfig=cloudConfig.faceConfig;
        faceAlgorithm=true;
        
    }

    if(cloudConfig.licensePlateConfig.updateAt!=config.licensePlateConfig.updateAt){
        config.licensePlateConfig=cloudConfig.licensePlateConfig;
        licensePlateAlgorithm=true;
    }

    if(cloudConfig.uniformConfig.updateAt!=config.uniformConfig.updateAt){
        config.uniformConfig=cloudConfig.uniformConfig;
        uniformAlgorithm=true;
        
    }

    if(config.timerSettings.updateAt!=cloudConfig.timerSettings.updateAt){
        timeChange=true;
    }
    if(!faceAlgorithm && !licensePlateAlgorithm && !uniformAlgorithm && !timeChange){
        return;
    }
    if(config.mqttConfig.updateAt!=cloudConfig.mqttConfig.updateAt){
        cloudConfig.mqttConfig.topic=config.mqttConfig.topic;
        runOrRebootMqtt(cloudConfig.mqttConfig,httpUrl,serialNumber);
    }
    __uint8_t alg= this->intToUint8t(faceAlgorithm,licensePlateAlgorithm,uniformAlgorithm,false) ;

    vides_data::DetectionParams params;

    params.newHumanDetectionLen =cloudConfig.uniformConfig.humanDetectionLen;
    params.newLicensePlateLen =cloudConfig.licensePlateConfig.licensePlateLen;
    params.newFaceLen =cloudConfig.faceConfig.faceLen;
    params.modelPaths = modelPaths;
    params.humanCarShapeConfidence =cloudConfig.uniformConfig.carShapeConfidence;
    params.uniformColor =cloudConfig.uniformConfig.uniformColor;
    params.faceMaps = localImageMap;
    params.numberFaces =cloudConfig.faceConfig.faceNumbers;
    params.faceConfidence =cloudConfig.faceConfig.confidence;
    params.algorithmPermissions =alg;
    params.isHigh =cloudConfig.licensePlateConfig.isHigh;
    params.maxNum = cloudConfig.licensePlateConfig.maxNum;
    params.useHalf = cloudConfig.licensePlateConfig.useHalf;
    params.boxConfThreshold = cloudConfig.licensePlateConfig.boxConfThreshold;
    params.nmsThreshold =cloudConfig.licensePlateConfig.nmsThreshold;
    params.recConfidenceThreshold = cloudConfig.licensePlateConfig.recConfidenceThreshold;


    algorithmTaskManage.releaseResources(params);
    if(config.timerSettings.updateAt!=cloudConfig.timerSettings.updateAt){
        if(config.timerSettings.deleteLogFileTimer!=cloudConfig.timerSettings.deleteLogFileTimer){
            deleteLogFileTimer->stop();
            deleteLogFileTimer->setInterval(cloudConfig.timerSettings.deleteLogFileTimer);
            deleteLogFileTimer->start();
        }
        if(config.timerSettings.devicePermissionSynTimer!=cloudConfig.timerSettings.devicePermissionSynTimer){
            dePermissionSynTimer->stop();
            dePermissionSynTimer->setInterval(cloudConfig.timerSettings.devicePermissionSynTimer);
            dePermissionSynTimer->start();
        }
        config.timerSettings = cloudConfig.timerSettings;
    }
    
}


CameraHandle* MainWindow::findHandle(QString sn){
    for (auto it = faceDetectionParkingPushs.begin(); it != faceDetectionParkingPushs.end(); ++it) {
        QString currentSn = it->second->getSSn();
        if (currentSn == sn) {
            CameraHandle* matchedHandle = it->second;
            return  matchedHandle;
        }
    }
    return  nullptr;
}
void MainWindow::sendJsonResponse(QTcpSocket* socket, int code, const QString& data, const QString& msg){
    QJsonObject jsonResponse;
    jsonResponse["code"] = code;
    jsonResponse["data"] = data;
    jsonResponse["msg"] = msg;
    
    QJsonDocument doc(jsonResponse);
    QByteArray jsonData = doc.toJson();
    
    socket->write(jsonData);
    socket->flush();
    socket->waitForBytesWritten();
    socket->disconnectFromHost();
}

void MainWindow::sendEmptyResponse(QTcpSocket* socket){
    sendJsonResponse(socket, 200, "", "Success");
}

void MainWindow::sendNotFoundResponse(QTcpSocket* socket){
    QString httpResponse = "HTTP/1.1 404 Not Found\r\n"
                           "Content-Type: text/html\r\n"
                           "Connection: Close\r\n\r\n"
                           "<html><body><h1>404 Not Found</h1>"
                           "<p>The requested URL was not found on this server.</p></body></html>";
    
    socket->write(httpResponse.toUtf8());
    socket->flush();
    socket->waitForBytesWritten();
    socket->disconnectFromHost();
}
void MainWindow::handleMatNewConnection(){
    QTcpSocket* socket = server.nextPendingConnection();
    
    QObject::connect(socket, &QTcpSocket::readyRead, [&, socket](){
        QByteArray requestData = socket->readAll();
        QString request(requestData);
        
        QRegExp urlRegEx("GET /cameras/([^/]+)/current_image HTTP");
        if(urlRegEx.indexIn(request) != -1) {
            QString sn = urlRegEx.cap(1);
            qInfo() << "Requested Camera SN: " << sn;
            bool foundCamera = false;
            for (auto it = faceDetectionParkingPushs.begin(); it != faceDetectionParkingPushs.end(); ++it) {
                QString currentSn = it->second->getSSn();
                if (currentSn == sn) {
                    CameraHandle* matchedHandle = it->second;
                    std::vector<uchar> buffer;
                    matchedHandle->getCurrentFrame(buffer);
                    
                    QByteArray byteArray(reinterpret_cast<const char*>(buffer.data()), buffer.size());
                    QString base64Data = byteArray.toBase64();
                    
                    sendJsonResponse(socket, 200, base64Data, "Success");
                    foundCamera = true;
                    break;
                }
            }
            
            if(!foundCamera){
                sendEmptyResponse(socket);
            }
        } else {
            sendNotFoundResponse(socket);
        }
    });
}

void MainWindow::modifyImagesAndNames(QString &modId){
    QString fullPathName;
    Common & instace= Common::getInstance();
    if(cloudImageMap.count(modId) <=0 ){
        return;
    }
    QString ossUrl= cloudImageMap.at(modId);
    HttpService httpService(ossUrl);
    
    vides_data::response *res= httpService.httpDownload(instace.getImages(),fullPathName);
    if(res->code!=0){
        qInfo()<<"httpFindCameras请求失败";
        instace.deleteObj(res);
        return ;
    }
    QString settingKey = QString("%1").arg(modId);
    qSetting->setValue(settingKey,fullPathName);
    localImageMap[modId]=fullPathName;
    instace.deleteObj(res);
}

void MainWindow::removeImageFiles(QString id){
    auto localIt = localImageMap.find(id);
    if (localIt != localImageMap.end()) {
        QString value = localIt->second;
        QFile file(value);
        if (!file.open(QIODevice::WriteOnly)) {
            qInfo() << "removeImageFiles open fail" << value;
        } else {
            file.remove();
        }
    }
}
void MainWindow::updateLocalFace(const QString &httpurl) {
    Common &instance = Common::getInstance();
    HttpService httpService(httpurl);
    QString serialNumber;
    std::list<vides_data::responseFaceReconition*> datas;
    this->findLocalSerialNumber(serialNumber);
    vides_data::response *res = httpService.httpFindFaceReconition(serialNumber, datas);
    
    if (res->code != 0) {
        qInfo() << "httpFindCameras请求失败";
        instance.deleteObj (res); // 手动释放资源
        return;
    }
    
    QSet<QString> dataIds;
    bool isChanged=false;
    for (const auto& item : datas) {
        dataIds.insert(item->img);
        
        if (cloudImageMap.count(item->id) > 0) {
            if (cloudImageMap.at(item->id) != item->img) {
                qSetting->beginGroup("cloudImageMap");
                QString settingKey = QString("%1").arg(item->id);
                qSetting->setValue(settingKey, item->img);
                qSetting->endGroup();
                
                cloudImageMap[item->id] = item->img;
                removeImageFiles(item->id);
                qSetting->beginGroup("localImageMap");
                this->modifyImagesAndNames(item->id);
                qSetting->endGroup();
                isChanged=true;
            }
        } else {
            qSetting->beginGroup("cloudImageMap");
            QString settingKey = QString("%1").arg(item->id);
            qSetting->setValue(settingKey, item->img);
            qSetting->endGroup();
            
            cloudImageMap[item->id] = item->img;
            
            qSetting->beginGroup("localImageMap");
            this->modifyImagesAndNames(item->id);
            qSetting->endGroup();
            isChanged=true;
        }
    }
    
    for (auto it = cloudImageMap.begin(); it != cloudImageMap.end();) {
        if (!dataIds.contains(it->second)) {
            qSetting->beginGroup("cloudImageMap");
            qSetting->remove(it->first);
            qSetting->endGroup();
            auto localIt = localImageMap.find(it->first);
            if (localIt != localImageMap.end()) {
                QFile file(localIt->second);
                if (!file.open(QIODevice::WriteOnly)) {
                    qInfo() << "open fail" << localIt->second;
                } else {
                    file.remove();
                    qSetting->beginGroup("localImageMap");
                    qSetting->remove(localIt->first);
                    qSetting->endGroup();
                    
                    localImageMap.erase(localIt);
                }
            }
            isChanged=true;
            it = cloudImageMap.erase(it);
        } else {
            ++it;
        }
    }
    
    if (isChanged) {
        float confidence=config.faceConfig.confidence;
        qSetting->value("devices/confidence").toFloat();
        
        int faceNumbers=config.faceConfig.faceNumbers;
        
        AlgorithmTaskManage &algorithmTaskManage= AlgorithmTaskManage::getInstance();
        
        if (cloudImageMap.empty()) {
            // 如果云端映射现在为空，移除所有特征
            //faceRecognition.featureRemove();
            algorithmTaskManage.modifyImageFeature(localImageMap,faceNumbers,confidence,true);
        } else {
            //float confidence=qSetting->value("devices/confidence").toFloat();
            //int faceNumbers=qSetting->value("devices/faceNumbers").toInt();
            
            qInfo()<<"startMap != endMap-->";
            // faceRecognition.initSourceImageMap(localImageMap,faceNumbers, confidence);
            algorithmTaskManage.modifyImageFeature(localImageMap,faceNumbers,confidence,false);
            
        }
    }
    for (vides_data::responseFaceReconition* data : datas)
    {
        instance.deleteObj(data);
    }
    datas.clear(); // 清空列表
    instance.deleteObj(res);
}
void MainWindow::findLocalSerialNumber(QString &serialNumber){
    if(vides_data::isVirtualMachine()){
        serialNumber = QSysInfo::machineUniqueId();
    }else{
        if(localSn.length()>0){
            serialNumber=localSn;
        }else {
            QString number= vides_data::getCpuSerialNumber();
            if(number.length()<=0){
                char cpu_id_arm[40] = {0};
                int  result = vides_data::GetCpuIdByAsm_arm(cpu_id_arm); //EC-06-08-00-FF-FB-8B-1F
                if (result>= 0)
                {
                    number=cpu_id_arm;
                }
            }
            
            serialNumber =number.trimmed();
            localSn=serialNumber;
        }
    }
}
void MainWindow::clearHandle(QString sDevId, int nDevPort){
    QString key = sDevId + ":" + QString::number(nDevPort);
    Common & instace= Common::getInstance();
    auto it = this->faceDetectionParkingPushs.find(key);
    if (it != this->faceDetectionParkingPushs.end()) {
        MediaFaceImage* mediaFaceImage= MediaFaceImage::getInstance();
        
        qInfo()<<"clearHandle:离线的设备是:"<<key;
        CameraHandle* offlineCameraHandle = it->second; // 注意使用->second获取值
        int hDevice=offlineCameraHandle->getHdevice();
        instace.deleteObj(offlineCameraHandle);
        this->faceDetectionParkingPushs.erase(it); // 使用迭代器来删除，更安全，避免潜在的问题
        mediaFaceImage->clearCurrentDevice(hDevice);
    }
}
void MainWindow::clearOfflineCameraHandle(QString sDevId, int nDevPort) {
    emit shutdownSignals(sDevId,nDevPort);
}
//平台有 盒子没有 盒子开启
//平台没有 盒子有 盒子关闭
void MainWindow::startCamera(const QString &httpurl){
    Common & instace= Common::getInstance();
    MediaFaceImage* mediaFaceImage= MediaFaceImage::getInstance();
    QString nonConstHttpUrl = std::remove_const<QString>::type(httpurl);
    
    vides_data::responseDeviceData devices;
    // QString serialNumber = QSysInfo::machineUniqueId();
    QString serialNumber;
    findLocalSerialNumber(serialNumber);
    vides_data::requestDeviceStatus reStatus;
    reStatus.sSn=serialNumber;
    reStatus.status=1;
    reStatus.type=1;
    reStatus.ip_addr=instace.GetLocalIp();
    reStatus.firmware_version=APP_VERSION;
    
    HttpService httpService(httpurl);
    vides_data::response *re= httpService.httpFindCameras(serialNumber,devices);
    if(re->code==0 || re->code==20004){
        
        std::map<QString,vides_data::localDeviceStatus*> localDevices;
        mediaFaceImage->SdkSearchDevicesSyn(localDevices);
        if(localDevices.size()<=0){
            httpService.setHttpUrl(httpurl);
            vides_data::response *res=httpService.httpPostDeviceStatus(reStatus);
            if(res->code!=0){
                qInfo()<<"盒子状态上报失败 code:"<<res->code<<"msg:"<<res->msg;
            }
            instace.deleteObj(re);
            instace.deleteObj(res);
            return ;
        }

        vides_data::responseConfig cloudConfig;
        httpService.setHttpUrl(httpurl);
        vides_data::response *res_config= httpService.httpDeviceConfig(serialNumber,cloudConfig);
        if(res_config->code!=0){
            qInfo()<<"请求远程商户配置失败";
            instace.deleteObj(res_config);
            return ;
        }
        instace.deleteObj(res_config);
        divParameterUpdate(cloudConfig,nonConstHttpUrl,serialNumber);

        for (const auto& device : devices.list) {
            if(localDevices.count(device.sSn)>0 ){
                vides_data::localDeviceStatus* localDevice= localDevices.at(device.sSn);
                QString ipAddress= QString("%1.%2.%3.%4").arg(localDevice->HostIP.c[0]).arg(localDevice->HostIP.c[1]).arg(localDevice->HostIP.c[2]).arg(localDevice->HostIP.c[3]);
                //this->gatewayRandomIp(ipAddress);
                QString key = ipAddress + ":" + QString::number(localDevice->TCPPort);
                
                httpService.setHttpUrl(httpurl);
                
                vides_data::responseConfig devConfig;
                
                vides_data::response *devRes=httpService.httpDeviceConfig(device.sSn,devConfig);
                if(devRes->code!=0){
                    qInfo()<<"请求相机配置失败";
                    instace.deleteObj(devRes);
                    continue;
                }
                instace.deleteObj(devRes);
                if(faceDetectionParkingPushs.count(key)<=0){
                    vides_data::cameraParameters parameter;
                    parameter.sDevId=ipAddress;
                    parameter.nDevPort=localDevice->TCPPort;
                    parameter.sUserName=devConfig.camera.username;
                    parameter.sPassword=devConfig.camera.password;
                    parameter.channel=localDevice->ChannelNum;
                    parameter.httpUrl=nonConstHttpUrl;
                    parameter.sSn=device.sSn;
                    //parameter.rtspUrl="rtsp://192.168.10.131:554/user=admin&password=&channel=1&stream=1.sdp?";
                    //parameter.rtspUrl=std::move(QString("rtsp://admin:@%1/stream1").arg(ipAddress));
                    this->initCameras(parameter,devConfig,device.areas,reStatus.camera_info_list);
                }
                else {
                    CameraHandle *indexHandle=findHandle(device.sSn);
                    if(indexHandle!=nullptr &&device.is_reboot){
                        indexHandle->deviceReboot();
                    }else {
                        auto it = this->faceDetectionParkingPushs.find(key);
                        if (it != this->faceDetectionParkingPushs.end()) {
                            CameraHandle* offlineCameraHandle = it->second; // 注意使用->second获取值
                            vides_data::requestCameraInfo camera_info;
                            camera_info.sSn=offlineCameraHandle->getSSn();
                            offlineCameraHandle->findIp(camera_info.ip_addr);
                            offlineCameraHandle->findFirmwareVersion(camera_info.firmware_version);
                            
                            reStatus.camera_info_list.push_front(camera_info);

                            __uint8_t new_algorithm= intToUint8t(devConfig.faceConfig.isOn,devConfig.licensePlateConfig.isOn,devConfig.uniformConfig.isOn,devConfig.humanConfig.isOn);

                            offlineCameraHandle->cameraParameterUpdate(devConfig);
                            offlineCameraHandle->initAlgorithmPermissions(new_algorithm);
                            if(!offlineCameraHandle->compareLists(device.areas)){
                                offlineCameraHandle->updateParkMapAndParkingSpaceInfos(device.areas);
                            }
                        }
                    }
                    
                }
            }
        }
        
        this->deleteCloudNotCamer(localDevices, devices.list);
        
        for (auto& pair : localDevices) {
            if (pair.second != nullptr) {  // 如果对象未被删除（即不为nullptr）
                instace.deleteObj(pair.second);
            }
        }
        // 清空 localDevices 容器
        localDevices.clear();
    }
    
    httpService.setHttpUrl(httpurl);
    vides_data::response *res=httpService.httpPostDeviceStatus(reStatus);
    if(res->code!=0){
        qInfo()<<"盒子状态上报失败 code:"<<res->code<<"msg:"<<res->msg;
    }
    instace.deleteObj(res);
    
    
    
    updateLocalFace(httpurl);
    instace.deleteObj(re);
    
}

bool MainWindow::isDeviceInList(const QString& deviceId, const std::list<vides_data::responseDeviceStatus>& devices) {
    auto it = std::find_if(devices.begin(), devices.end(), [&deviceId](const vides_data::responseDeviceStatus& device) {
        return deviceId == device.sSn; // 假设 sSn 是 std::string 类型，需要转换
    });
    return it != devices.end(); // 如果迭代器不是end，说明找到了匹配项
}
//从localDevices中过滤出不在devices列表中的设备
void MainWindow::deleteCloudNotCamer(const std::map<QString, vides_data::localDeviceStatus*>& localDevices,
                                     const std::list<vides_data::responseDeviceStatus>& devices) {
    for (auto localDevice : localDevices) {
        vides_data::localDeviceStatus* value = localDevice.second; // 使用 .second 访问值
        if (!this->isDeviceInList(value->sSn, devices)) {
            QString ipAddress = QString("%1.%2.%3.%4").arg(value->HostIP.c[0]).arg(value->HostIP.c[1]).arg(value->HostIP.c[2]).arg(value->HostIP.c[3]);
            QString key = ipAddress + ":" + QString::number(value->TCPPort);
            clearOfflineCameraHandle(ipAddress,value->TCPPort);
        }
    }
}

void MainWindow::initDevConfigSyn(CameraHandle *cameraHandle,vides_data::responseConfig &devConfig){
    Common & instace= Common::getInstance();
    QString time= instace.getTimeString();
    cameraHandle->sdkDevSystemTimeZoneSyn(time);
    QString recor;
    initRecordingToString(recor);
    QByteArray bRecor =recor.toUtf8();
    const char* cRecor=bRecor.data();
    cameraHandle->sdkRecordCfg(cRecor);

    QString enCode_one;

    initDeviceEncodeToString(devConfig,enCode_one);
    QByteArray benCode_one =enCode_one.toUtf8();
    const char* b_one=benCode_one.data();
    cameraHandle->sdkEncodeCfg(b_one);
}

void MainWindow::initDeviceEncodeToString(vides_data::responseConfig &source, QString &targetCodeJson){
    // 创建 JSON 对象
    QJsonObject rootObject;
    
    // 添加 ExtraFormat 到 JSON 对象中
    QJsonObject extraFormatObject;
    QJsonObject videoObjectExtra = {
        {"BitRate", source.extraFormat.BitRate},
        {"BitRateControl",source.extraFormat.BitRateControl},
        {"Compression", source.extraFormat.Compression},
        {"FPS", source.extraFormat.FPS},
        {"GOP", source.extraFormat.GOP},
        {"Quality", source.extraFormat.Quality},
        {"Resolution", source.extraFormat.Resolution},
        {"VirtualGOP", source.extraFormat.VirtualGOP}
    };
    extraFormatObject["VideoEnable"] = source.extraFormat.VideoEnable;
    extraFormatObject["AudioEnable"] =source.extraFormat.AudioEnable;
    extraFormatObject["Video"] = videoObjectExtra;
    rootObject["ExtraFormat"] = extraFormatObject;
    
    // 添加 MainFormat 到 JSON 对象中
    QJsonObject mainFormatObject;
    QJsonObject videoObjectMain = {
        {"BitRate", source.mainFormat.BitRate},
        {"BitRateControl", source.mainFormat.BitRateControl},
        {"Compression", source.mainFormat.Compression},
        {"FPS", source.mainFormat.FPS},
        {"GOP", source.mainFormat.GOP},
        {"Quality", source.mainFormat.Quality},
        {"Resolution", source.mainFormat.Resolution},
        {"VirtualGOP",source.mainFormat.VirtualGOP}
    };
    mainFormatObject["VideoEnable"] = source.mainFormat.VideoEnable;
    mainFormatObject["AudioEnable"] =source.mainFormat.AudioEnable;
    mainFormatObject["Video"] = videoObjectMain;
    rootObject["MainFormat"] = mainFormatObject;
    QJsonArray jsonArray;
    jsonArray.append(rootObject);
    
    // 将 JSON 对象转换为 JSON 文档
    QJsonDocument jsonDocument(jsonArray);
    targetCodeJson = QString::fromUtf8(jsonDocument.toJson());
}


void MainWindow::initEncodeToString(QString &enCodeJson) {
    // 创建 JSON 对象
    QJsonObject rootObject;
    
    // 添加 ExtraFormat 到 JSON 对象中
    QJsonObject extraFormatObject;
    QJsonObject videoObjectExtra = {
        //        {"BitRate", qSetting->value("ExtraFormat/Video.BitRate").toInt()},
        {"BitRateControl", qSetting->value("ExtraFormat/Video.BitRateControl").toString()},
        {"Compression", qSetting->value("ExtraFormat/Video.Compression").toString()},
        {"FPS", qSetting->value("ExtraFormat/Video.FPS").toInt()},
        {"GOP", qSetting->value("ExtraFormat/Video.GOP").toInt()},
        {"Quality", qSetting->value("ExtraFormat/Video.Quality").toInt()},
        {"Resolution", qSetting->value("ExtraFormat/Video.Resolution").toString()},
        {"VirtualGOP", qSetting->value("ExtraFormat/Video.VirtualGOP").toInt()}
    };
    extraFormatObject["VideoEnable"] = qSetting->value("ExtraFormat/VideoEnable").toBool();
    extraFormatObject["AudioEnable"] = qSetting->value("ExtraFormat/AudioEnable").toBool();
    extraFormatObject["Video"] = videoObjectExtra;
    rootObject["ExtraFormat"] = extraFormatObject;
    
    // 添加 MainFormat 到 JSON 对象中
    QJsonObject mainFormatObject;
    QJsonObject videoObjectMain = {
        //        {"BitRate", qSetting->value("MainFormat/Video.BitRate").toInt()},
        {"BitRateControl", qSetting->value("MainFormat/Video.BitRateControl").toString()},
        {"Compression", qSetting->value("MainFormat/Video.Compression").toString()},
        {"FPS", qSetting->value("MainFormat/Video.FPS").toInt()},
        {"GOP", qSetting->value("MainFormat/Video.GOP").toInt()},
        {"Quality", qSetting->value("MainFormat/Video.Quality").toInt()},
        {"Resolution", qSetting->value("MainFormat/Video.Resolution").toString()},
        {"VirtualGOP", qSetting->value("MainFormat/Video.VirtualGOP").toInt()}
    };
    mainFormatObject["VideoEnable"] = qSetting->value("MainFormat/VideoEnable").toBool();
    mainFormatObject["AudioEnable"] = qSetting->value("MainFormat/AudioEnable").toBool();
    mainFormatObject["Video"] = videoObjectMain;
    rootObject["MainFormat"] = mainFormatObject;
    QJsonArray jsonArray;
    jsonArray.append(rootObject);
    
    // 将 JSON 对象转换为 JSON 文档
    QJsonDocument jsonDocument(jsonArray);
    enCodeJson = QString::fromUtf8(jsonDocument.toJson());
}

bool MainWindow::iniWorkSpVMn(vides_data::responseGb28181 *gb28181,QString &workSpWMn,QString &sn){
    qInfo()<<"iniWorkSpVMn=="<<sn;
    QString jsonfile=QCoreApplication::applicationDirPath()+"/camera_config.json";
    bool isEqual=true;
    
    // 读取 JSON 配置文件
    QFile file(jsonfile);
    if (!file.open(QIODevice::ReadOnly)) {
        qInfo() << "Failed to open the camera_config.json";
        return isEqual;
    }
    QJsonObject toJsonObject;
    
    // 解析 JSON 数据
    QByteArray jsonData = file.readAll();
    file.close();
    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
    QJsonObject rootObj = jsonDoc.object();
    
    // 获取 cameraconfigs 对象
    QJsonArray cameraConfigs = rootObj.value("cameraconfigs").toArray();
    bool found = false;
    for (int i = 0; i < cameraConfigs.size(); ++i) {
        QJsonObject config = cameraConfigs.at(i).toObject();
        if (config.contains("sn") && config.value("sn").toString() == sn) {
            found = true;
            QString Camreaid = config.value("Camreaid").toString();
            int iHsIntervalTime = config.value("iHsIntervalTime").toInt();
            int iRsAgedTime = config.value("iRsAgedTime").toInt();
            int sCsPort = config.value("sCsPort").toInt();
            QString szConnPass = config.value("szConnPass").toString();
            QString szCsIP = config.value("szCsIP").toString();
            QString szDeviceNO = config.value("szDeviceNO").toString();
            QString szServerDn = config.value("szServerDn").toString();
            QString szServerNo = config.value("szServerNo").toString();
            isEqual = (szCsIP == gb28181->sip_ip &&
                       sCsPort == gb28181->sip_port &&
                       szServerNo == gb28181->serial &&
                       szServerDn ==gb28181->realm &&
                       iRsAgedTime == gb28181->register_validity &&
                       iHsIntervalTime == gb28181->heartbeat_interval &&
                       szConnPass == gb28181->password &&
                       szDeviceNO == gb28181->device_id &&
                       Camreaid == gb28181->channel_id);
            if(!isEqual){
                config["Camreaid"]=gb28181->channel_id;
                config["szCsIP"]=gb28181->sip_ip ;
                config["szServerNo"]=gb28181->serial;
                config["sCsPort"]=gb28181->sip_port;
                config["szServerDn"]=gb28181->realm;
                config["iRsAgedTime"]=gb28181->register_validity;
                config["iHsIntervalTime"]=gb28181->heartbeat_interval;
                config["szConnPass"]=gb28181->password;
                config["szDeviceNO"]=gb28181->device_id;
                config["sn"]=sn;
                toJsonObject["szCsIP"]=gb28181->sip_ip ;
                toJsonObject["szServerNo"]=gb28181->serial;
                toJsonObject["sCsPort"]=gb28181->sip_port;
                toJsonObject["szServerDn"]=gb28181->realm;
                toJsonObject["iRsAgedTime"]=gb28181->register_validity;
                toJsonObject["iHsIntervalTime"]=gb28181->heartbeat_interval;
                toJsonObject["szConnPass"]=gb28181->password;
                toJsonObject["szDeviceNO"]=gb28181->device_id;
                
                QVariantList variantList;
                for (int i = 0; i < 64; ++i) {
                    variantList.append(QVariant(0));
                }
                
                QJsonArray levelArray = QJsonArray::fromVariantList(variantList);
                toJsonObject["AlarmLevel"]=levelArray;
                QStringList alarmidStrings;
                for (int i = 1; i <= 64; ++i) {
                    alarmidStrings.append("3402000000134000000" + QString::number(i, 10).rightJustified(2, '0'));
                }
                QJsonArray alarmidArray = QJsonArray::fromStringList(alarmidStrings);
                toJsonObject["Alarmid"]=alarmidArray;
                QVariantList variantListLevel;
                for (int i = 0; i < 64; ++i) {
                    variantListLevel.append(QVariant(0));
                }
                
                QJsonArray camreaLevelArray = QJsonArray::fromVariantList(variantListLevel);
                
                toJsonObject["CamreaLevel"]=camreaLevelArray;
                QStringList camreaidStrings;
                for (int i = 1; i <= 64; ++i) {
                    if(i==1){
                        camreaidStrings.append(gb28181->channel_id);
                    }else{
                        camreaidStrings.append("3402000000131000001" + QString::number(i, 10).rightJustified(2, '0'));
                    }
                }
                QJsonArray camreaidArray = QJsonArray::fromStringList(camreaidStrings);
                toJsonObject["Camreaid"]=camreaidArray;
                toJsonObject["HeartBeatCount"] = 0;
                toJsonObject["bCsEnable"] = true;
                toJsonObject["uiAlarmStateBlindEnable"] = static_cast<qint64>(4294967295);
                toJsonObject["uiAlarmStateConnectEnable"] = static_cast<qint64>(4294967295);
                toJsonObject["uiAlarmStateGpinEnable"] = static_cast<qint64>(4294967295);
                toJsonObject["uiAlarmStateLoseEnable"] = static_cast<qint64>(4294967295);
                toJsonObject["uiAlarmStateMotionEnable"] = static_cast<qint64>(4294967295);
                toJsonObject["uiAlarmStatePerformanceEnable"] = static_cast<qint64>(4294967295);
                toJsonObject["sUdpPort"] = 5060;
                cameraConfigs[i] = config; // 更新数组中的配置
                break;
            }
        }
    }
    if (!found) {
        QJsonObject newValue;
        newValue["sn"]=sn;
        newValue["Camreaid"]=gb28181->channel_id;
        newValue["szCsIP"]=gb28181->sip_ip ;
        newValue["szServerNo"]=gb28181->serial;
        newValue["sCsPort"]=gb28181->sip_port;
        newValue["szServerDn"]=gb28181->realm;
        newValue["iRsAgedTime"]=gb28181->register_validity;
        newValue["iHsIntervalTime"]=gb28181->heartbeat_interval;
        newValue["szConnPass"]=gb28181->password;
        newValue["szDeviceNO"]=gb28181->device_id;
        
        toJsonObject["szCsIP"]=gb28181->sip_ip ;
        toJsonObject["szServerNo"]=gb28181->serial;
        toJsonObject["sCsPort"]=gb28181->sip_port;
        toJsonObject["szServerDn"]=gb28181->realm;
        toJsonObject["iRsAgedTime"]=gb28181->register_validity;
        toJsonObject["iHsIntervalTime"]=gb28181->heartbeat_interval;
        toJsonObject["szConnPass"]=gb28181->password;
        toJsonObject["szDeviceNO"]=gb28181->device_id;
        
        QVariantList variantList;
        for (int i = 0; i < 64; ++i) {
            variantList.append(0);
        }
        
        QJsonArray levelArray = QJsonArray::fromVariantList(variantList);
        
        toJsonObject["AlarmLevel"]=levelArray;
        QStringList alarmidStrings;
        for (int i = 1; i <= 64; ++i) {
            alarmidStrings.append("3402000000134000000" + QString::number(i, 10).rightJustified(2, '0'));
        }
        QJsonArray alarmidArray = QJsonArray::fromStringList(alarmidStrings);
        toJsonObject["Alarmid"]=alarmidArray;
        QJsonArray camreaLevelArray;
        for (int i = 0; i < 64; ++i) {
            camreaLevelArray.append(0);
        }
        toJsonObject["CamreaLevel"]=camreaLevelArray;
        QStringList camreaidStrings;
        for (int i = 1; i <= 64; ++i) {
            if(i==1){
                camreaidStrings.append(gb28181->channel_id);
            }else{
                camreaidStrings.append("3402000000131000001" + QString::number(i, 10).rightJustified(2, '0'));
            }
        }
        QJsonArray camreaidArray = QJsonArray::fromStringList(camreaidStrings);
        toJsonObject["Camreaid"]=camreaidArray;
        toJsonObject["HeartBeatCount"] = 0;
        toJsonObject["bCsEnable"] = true;
        toJsonObject["uiAlarmStateBlindEnable"] = static_cast<qint64>(4294967295);
        toJsonObject["uiAlarmStateConnectEnable"] = static_cast<qint64>(4294967295);
        toJsonObject["uiAlarmStateGpinEnable"] = static_cast<qint64>(4294967295);
        toJsonObject["uiAlarmStateLoseEnable"] = static_cast<qint64>(4294967295);
        toJsonObject["uiAlarmStateMotionEnable"] = static_cast<qint64>(4294967295);
        toJsonObject["uiAlarmStatePerformanceEnable"] = static_cast<qint64>(4294967295);
        toJsonObject["sUdpPort"] = 5060;
        isEqual=false;
        cameraConfigs.append(newValue); // 添加新的配置到数组中
    }
    if(!isEqual){
        QJsonDocument doc(toJsonObject);
        QByteArray jsonData = doc.toJson(QJsonDocument::Compact);
        workSpWMn = QString::fromUtf8(jsonData);
        // 更新 JSON 数据
        rootObj["cameraconfigs"] = cameraConfigs;
        file.setFileName(jsonfile);
        if (!file.open(QIODevice::WriteOnly)) {
            qWarning("Cannot open file for writing");
            return true;
        }
        QJsonDocument saveDoc(rootObj);
        file.write(saveDoc.toJson());
        file.close();
        
    }
    return isEqual;
}

void MainWindow::initRecordingToString(QString &recorJson){
    QJsonObject jsonObject;
    
    // 读取 Mask 数据
    QJsonArray maskArray;
    // 遍历所有掩码
    for (int i = 1; i <= 7; i++) {
        QString maskKey = QString("Mask/Mask_%1").arg(i);
        // 读取掩码值。存储为QStringList，就像在ini文件中定义的一样
        QStringList maskValues = qSetting->value(maskKey).toStringList();
        QJsonArray maskSubArray;
        
        foreach (const QString &value, maskValues) {
            maskSubArray.append(value.trimmed());
        }
        maskArray.append(maskSubArray);
    }
    
    jsonObject["Mask"] = maskArray;
    
    // 读取 Packet 数据
    jsonObject["PacketLength"] =qSetting->value("Packet/PacketLength").toInt();
    jsonObject["PreRecord"] = qSetting->value("Packet/PreRecord").toInt();
    jsonObject["RecordMode"] = qSetting->value("Packet/RecordMode").toString();
    jsonObject["Redundancy"] = qSetting->value("Packet/Redundancy").toBool();
    
    
    // 读取 TimeSection 数据
    QJsonArray timeArray;
    for (int ts = 1; ts <= 7; ts++) {
        QString tsKey = QString("TimeSection/TimeSection_%1").arg(ts);
        
        // 读取掩码值。存储为QStringList，就像在ini文件中定义的一样
        QStringList tsValues = qSetting->value(tsKey).toStringList();
        QJsonArray timeSubArray;
        foreach (const QString &value, tsValues) {
            timeSubArray.append(value.trimmed());
        }
        timeArray.append(timeSubArray);
    }
    jsonObject["TimeSection"] = timeArray;
    QJsonArray jsonArray;
    jsonArray.append(jsonObject);
    QJsonDocument jsonDocument(jsonArray);
    recorJson =  QString::fromUtf8(jsonDocument.toJson());
}

__uint8_t MainWindow::intToUint8t(bool faceAlgorithm, bool licensePlateAlgorithm, bool uniformAlgorithm,bool humanAlgorithm) {
    __uint8_t result = 0;
    //人形识别对应最高高位（第3位）
    result |= (humanAlgorithm ? 1 : 0) << 3;

    // 工服识别对应最高位（第2位）
    result |= (uniformAlgorithm ? 1 : 0) << 2;
    
    // 人脸识别对应次高位（第1位）
    result |= (faceAlgorithm ? 1 : 0) << 1;
    
    // 车牌识别对应最低位（第0位）
    result |= (licensePlateAlgorithm ? 1 : 0);

    qInfo()<<"算法结果"<<result;

    return result;
}
void MainWindow::initCameras(vides_data::cameraParameters &parameter,vides_data::responseConfig &devConfig,const std::list<vides_data::responseArea>&areas,std::list<vides_data::requestCameraInfo>&camera_info_list){
    MediaFaceImage* mediaFaceImage= MediaFaceImage::getInstance();
    Common & instace= Common::getInstance();
    
    int image_save=devConfig.camera.imageSave;
    float heightReference=devConfig.camera.heightReference;
    CameraHandle * cameraHandle =new CameraHandle(parameter.sDevId,parameter.httpUrl,parameter.sSn,parameter.channel,image_save,heightReference,devConfig);
    
    int sdk_handle=cameraHandle->sdkDevLoginSyn(parameter.sDevId,parameter.nDevPort,parameter.sUserName,parameter.sPassword,3000);
    qInfo()<<"句柄为2:"<<sdk_handle;
    if(sdk_handle<=0){
        qInfo() << "登录失败";
        return ;
    }
    mediaFaceImage->setMap(sdk_handle,cameraHandle);


    
    initDevConfigSyn(cameraHandle,devConfig);
    cameraHandle->sdkDevSetAlarmListener(sdk_handle,0);

    
    int synTime=devConfig.camera.devSnapSynTimer;
    uint64 face_frequency=devConfig.faceConfig.faceFrequency;
    float carConfidenceMax=devConfig.licensePlateConfig.carConfidenceMax;
    float carConfidenceMin=devConfig.licensePlateConfig.carConfidenceMin;
    
    cameraHandle->initSdkRealTimeDevSnapSyn(sdk_handle,synTime,face_frequency);
    cameraHandle->setCarConfidenceMaxAndMin(carConfidenceMax,carConfidenceMin);
    
    //    QString pwd="admin2024";
    //    QString sid="MERCURY_8C4F";
    //    cameraHandle->sdkWifi(pwd,sid);
    vides_data::requestCameraInfo camera_info;
    camera_info.sSn=parameter.sSn;
    camera_info.ip_addr=parameter.sDevId;
    cameraHandle->findFirmwareVersion(camera_info.firmware_version);
    
    camera_info_list.push_front(camera_info);

    __uint8_t new_algorithm= (devConfig.faceConfig.isOn,devConfig.licensePlateConfig.isOn,devConfig.uniformConfig.isOn,devConfig.humanConfig.isOn);
    cameraHandle->initAlgorithmPermissions(new_algorithm);
    
    cameraHandle->initParkingSpaceInfo(areas);
    
    QString key =parameter.sDevId + ":" + QString::number(parameter.nDevPort);
    faceDetectionParkingPushs[key]= cameraHandle;
    HttpService httpService(parameter.httpUrl);
    vides_data::response *res=httpService.httpFindGb28181Config(parameter.sSn);
    if(res->code!=0){
        qInfo()<<"请求摄像头gb28181配置失败";
        instace.deleteObj(res);
        return;
    }
    vides_data::responseGb28181 *gb281 = reinterpret_cast<vides_data::responseGb28181*>(res->data);
    //    QString stGb281;
    //    bool re= iniWorkSpVMn(gb281,stGb281,parameter.sSn);
    //    if(!re){
    //        QByteArray bGb =stGb281.toUtf8();
    //        const char* cGb=bGb.data();
    //        cameraHandle->sdkDevSpvMn(cGb);
    //    }
    cameraHandle->updateSdkDevSpvMn(gb281);
    instace.deleteObj(gb281);
    instace.deleteObj(res);
}

void MainWindow::setVideoPath(int flag, const QString& path) {
    Common& instance = Common::getInstance();
    switch (flag) {
    case 0x00:
        instance.setVideoOut(path);
        break;
    case 0x01:
        instance.setVideoDownload(path);
        break;
    case 0x02:
        instance.setImages(path);
        break;
    default:
        // 处理未知的标志值
        break;
    }
}
void MainWindow::createDirectory(int flag,const QString& dirName, const QString& successMsg, const QString& failureMsg) {
    QDir directory;
    if (directory.exists(dirName)) {
        qInfo() << successMsg << "目录已存在";
        setVideoPath(flag, directory.absoluteFilePath(dirName));
    } else {
        if (directory.mkdir(dirName)) {
            qInfo() << successMsg << "目录创建成功";
            setVideoPath(flag, directory.absoluteFilePath(dirName));
        } else {
            qInfo() << failureMsg << "目录创建失败";
        }
    }
}

void MainWindow::initCommon(){
    createDirectory(0x01,"frame_images", "目录创建成功", "目录创建失败");
    createDirectory(0x00,"frame_video", "创建视频目录成功", "视频目录创建失败");
    createDirectory(0x02,"images", "图片目录创建成功", "图片目录创建失败");
}

MainWindow::~MainWindow()
{
    //delete ui;
    Common & instace= Common::getInstance();
    instace.deleteObj(qSetting);
    instace.deleteObj(deleteLogFileTimer);
    instace.deleteObj(dePermissionSynTimer);
    
    for(auto iter = faceDetectionParkingPushs.begin(); iter != faceDetectionParkingPushs.end(); ++iter) {
        instace.deleteObj( iter->second);
    }
    // 清空 handleMap
    faceDetectionParkingPushs.clear();
    
    LogHandler::Get().uninstallMessageHandler();
    
}

void MainWindow::deleteLogFile(){
    QDateTime now = QDateTime::currentDateTime();
    QDir  logDir("log");
    // 前7天
    QDateTime dateTime1 = now.addDays(-7);
    QDateTime dateTime2;
    
    QString logPath = logDir.absoluteFilePath(""); // 日志的路径
    
    QDir dir(logPath);
    
    QStringList filename ;
    filename << "*.log";//可叠加，可使用通配符筛选
    
    QFileInfoList fileList = dir.entryInfoList(filename);
    foreach (QFileInfo f, fileList) {
        // "."和".."跳过
        if (f.baseName() == "" || f.baseName()=="today" )
            continue;
        
        dateTime2 = QDateTime::fromString(f.baseName(), "yyyy-MM-dd");
        if (dateTime2 < dateTime1) { // 只要日志时间小于前7天的时间就删除
            dir.remove(f.absoluteFilePath());
        }
    }
}

void MainWindow::initFaceFaceRecognition() {
    
    qSetting->beginGroup("cloudImageMap");
    
    QStringList keys = qSetting->childKeys();
    
    foreach(QString key, keys) {
        QString value = qSetting->value(key).toString();
        cloudImageMap[key]=value;
    }
    qSetting->endGroup();
    qSetting->beginGroup("localImageMap");
    QStringList lokeys = qSetting->childKeys();
    
    foreach(QString lk, lokeys) {
        // 获取键对应的值
        QString value = qSetting->value(lk).toString();
        localImageMap[lk]=value;
    }
    qSetting->endGroup();
}
