#include "Common.h"
#include "LicensePlateRecognition.h"
#include "ScopeSemaphoreExit.h"



LicensePlateRecognition::LicensePlateRecognition(const QString &modelPaths,bool is_high,int maxNum,
                                                 bool useHalf,float boxThreshold,float nmsThreshold,float recThreshold) {

    HLPR_ContextConfiguration configuration = {0};
    QByteArray && by_mpath=modelPaths.toUtf8();
    char* m_path=by_mpath.data();
    configuration.models_path = m_path;
    configuration.max_num = maxNum;
    if(is_high){
        configuration.det_level = DETECT_LEVEL_HIGH;
    }else{
        configuration.det_level = DETECT_LEVEL_LOW;
    }
    configuration.use_half = useHalf;
    configuration.nms_threshold =nmsThreshold;
    configuration.rec_confidence_threshold = recThreshold;
    configuration.box_conf_threshold = boxThreshold;
    configuration.threads = 1;
    ctx = HLPR_CreateContext(&configuration);
}
LicensePlateRecognition::LicensePlateRecognition(){

}

LicensePlateRecognition::~LicensePlateRecognition(){
    static int i=0;
    if(ctx!=nullptr){
        HLPR_ReleaseContext(ctx);
        qInfo()<<"车牌析构"<<++i;
    }

}

void LicensePlateRecognition::oldLicensePlateNumber(const cv::Mat &source,const QString &modelPaths,QString & lpNumber){
    HLPR_ImageData data = {0};
    data.data = source.data;
    data.width = source.cols;
    data.height = source.rows;
    data.format = STREAM_BGR;
    data.rotation = CAMERA_ROTATION_0;
    // create DataBuffer
    P_HLPR_DataBuffer buffer = HLPR_CreateDataBuffer(&data);
    
    // 检测图片数据流是否正确，如果出现崩溃或图像不符合预期 则表示数据流格式异常导致内部编码出错
    HLPR_DataBufferTest(buffer, "test_buffer.jpg");
    
    // create context
    HLPR_ContextConfiguration configuration = {0};
    QByteArray && by_mpath=modelPaths.toUtf8();
    char* m_path=by_mpath.data();
    configuration.models_path = m_path;
    configuration.max_num = 5;
    configuration.det_level = DETECT_LEVEL_HIGH;
    configuration.use_half = false;
    configuration.nms_threshold = 0.5f;
    configuration.rec_confidence_threshold = 0.8f;
    configuration.box_conf_threshold = 0.30f;
    configuration.threads = 1;
    P_HLPR_Context ctx1 = HLPR_CreateContext(&configuration);
    HREESULT ret = HLPR_ContextQueryStatus(ctx1);
    if (ret != HResultCode::Ok) {
        printf("create error.\n");
        return ;
    }
    // exec plate recognition
    HLPR_PlateResultList results = {0};
    HLPR_ContextUpdateStream(ctx1, buffer, &results);
    
    
    
    QStringList lpResults;
    for (int i = 0; i < results.plate_size; ++i) {
        std::string type;
        if (results.plates[i].type == HLPR_PlateType::PLATE_TYPE_UNKNOWN) {
            type = "未知";
        } else {
            type = types[results.plates[i].type];
        }
        QString plateResult = QString("第%1个,%2,车牌号:%3,置信度:%4,左上角点x坐标:%5,左上角点y坐标:%6,右下角点x坐标:%7,右下角点y坐标:%8")
                .arg(i + 1).arg(type.c_str()).arg(results.plates[i].code)
                .arg(results.plates[i].text_confidence).arg(results.plates[i].x1, 0, 'Q', 4)
                .arg(results.plates[i].y1, 0, 'Q', 4).arg(results.plates[i].x2, 0, 'Q', 4)
                .arg(results.plates[i].y2, 0, 'Q', 4);
        
        lpResults.append(plateResult);
    }
    
    lpNumber =lpResults.join("\n");
    // release buffer
    HLPR_ReleaseDataBuffer(buffer);
    // release context
    HLPR_ReleaseContext(ctx1);
}

void LicensePlateRecognition::replaceWith1And0(QString &code) {
    code.replace(QRegularExpression("[Ii]"), "1");
    code.replace(QRegularExpression("[Oo]"), "0");

}
void LicensePlateRecognition::filterLicensePlateConfidenceMax(vides_data::requestLicensePlate &plate, vides_data::LicensePlate &max) {
    std::list<vides_data::LicensePlate> &plates = plate.plates; // 使用引用避免复制列表

    if (plates.empty()) { // 检查列表是否为空
        // 如果列表为空，可能需要设定一个默认值或者抛出异常，这里简单地不改变max
        return;
    }

    max = plates.front(); // 初始化max为第一个元素
    float maxConfidence = max.text_confidence;

    for (auto it = plates.begin(); it != plates.end(); ++it) {
        if (it->text_confidence > maxConfidence) {
            max = *it; // 发现更高信心值的LicensePlate，更新max
            maxConfidence = it->text_confidence;
        }
    }
}

void LicensePlateRecognition::licensePlateNumber(const cv::Mat &source, QString &lpNumber,vides_data::requestLicensePlate &plate,
                                                 qint64 currentTime) {
    thread_time.store(QDateTime::currentMSecsSinceEpoch(), std::memory_order_release);

    // 执行一帧图像数据检测行人
    // create ImageData
    HLPR_ImageData data = {0};
    data.data = source.data;
    data.width = source.cols;
    data.height = source.rows;
    data.format = STREAM_BGR;
    data.rotation = CAMERA_ROTATION_0;
    // create DataBuffer
    P_HLPR_DataBuffer buffer = HLPR_CreateDataBuffer(&data);
    ScopeSemaphoreExit streamGuard([this, buffer]() {
        isRunning.store(false, std::memory_order_release);
        HLPR_ReleaseDataBuffer(buffer);

    });
    HREESULT ret = HLPR_ContextQueryStatus(ctx);
    if (ret != HResultCode::Ok) {
        qInfo()<<QString("create error");
        return ;
    }
    // exec plate recognition
    HLPR_PlateResultList results = {0};
    HLPR_ContextUpdateStream(ctx, buffer, &results);
    
    if (results.plate_size <= 0) {
        return;
    }
    
    QStringList lpResults;
    for (int i = 0; i < results.plate_size; ++i) {
        std::string type;
        if (results.plates[i].type == HLPR_PlateType::PLATE_TYPE_UNKNOWN) {
            type = "未知";
        } else {
            type = types[results.plates[i].type];
        }
        vides_data::LicensePlate newPlate;
        newPlate.time=currentTime;
        newPlate.new_color=QString::fromStdString(type);
        QString car_nuber=QString::fromUtf8(results.plates[i].code);
        replaceWith1And0(car_nuber);
        newPlate.new_plate=car_nuber;
        newPlate.text_confidence=results.plates[i].text_confidence;
        vides_data::ParkingArea area;
        area.topLeftCornerX=results.plates[i].x1;
        area.topLeftCornerY=results.plates[i].y1;
        area.bottomLeftCornerX=results.plates[i].x1;
        area.bottomLeftCornerY=results.plates[i].y2;
        area.topRightCornerX=results.plates[i].x2;  // 修改这里
        area.topRightCornerY=results.plates[i].y1;  // 修改这里
        area.bottomRightCornerX=results.plates[i].x2;
        area.bottomRightCornerY=results.plates[i].y2;
        newPlate.recognition=area;
        QString plateResult = QString("第%1个,%2,车牌号:%3,置信度:%4,左上角点x坐标:%5,左上角点y坐标:%6,右下角点x坐标:%7,右下角点y坐标:%8")
                .arg(i + 1).arg(type.c_str()).arg(results.plates[i].code)
                .arg(results.plates[i].text_confidence).arg(results.plates[i].x1, 0, 'Q', 4)
                .arg(results.plates[i].y1, 0, 'Q', 4).arg(results.plates[i].x2, 0, 'Q', 4)
                .arg(results.plates[i].y2, 0, 'Q', 4);
        //QString plateResult = QString(results.plates[i].code);
        plate.plates.push_front(newPlate);
        lpResults.append(plateResult);
    }
    lpNumber =lpResults.join("\t");
    

}


