#include "Common.h"
#include "HumanDetection.h"

#include <QDateTime>

HumanDetection::HumanDetection(const QString &modelPaths,
                               float carShapeConfidence) : heightReference(250.0f){
    QByteArray && by_mpath=modelPaths.toUtf8();
    char* m_path=by_mpath.data();
    detector = TCV_CreateHumanDetector(m_path,1);
    
    TCV_HumanDetectorSetHumanThreshold(detector,0.5f);
    TCV_HumanDetectorSetCarThreshold(detector,carShapeConfidence);
    
}
HumanDetection::~HumanDetection(){
    static int i=0;
    if(detector!=nullptr){
        TCV_ReleaseHumanDetector(detector);
        qInfo()<<"工服析构"<<++i;
        detector=nullptr;
    }
}
void HumanDetection::draw_human_on_image(const cv::Mat& image, const TCV_ObjectLocation* boxes, int size) {
    for (int i = 0; i < size; ++i) {
        const auto& box = boxes[i];
        cv::Scalar color = cv::Scalar(0, 255, 0); // Green color for boxes
        cv::Point topLeft(box.x1, box.y1);
        cv::Point bottomRight(box.x2, box.y2);
        cv::rectangle(image, topLeft, bottomRight, color, 2); // Draw rectangle on image
        
        // Determine text to display based on the uniform value
        std::string text;
        switch (box.uniform) {
        case 0: text = "Other"; break;
        case 1: text = "Uniform 1"; break;
        case 2: text = "Uniform 2"; break;
        default: text = "Unknown"; break;
        }
        
        // Set text color and size
        int fontFace = cv::FONT_HERSHEY_SIMPLEX;
        double fontScale = 1.5;
        int thickness = 2;
        cv::Scalar textColor(0, 0, 255); // Red color for text
        
        // Calculate text size to position it correctly
        int baseline;
        cv::Size textSize = cv::getTextSize(text, fontFace, fontScale, thickness, &baseline);
        
        // Position text at the top center of the rectangle
        cv::Point textOrigin(
                    topLeft.x + (bottomRight.x - topLeft.x)/2 - textSize.width/2,
                    topLeft.y - baseline - 2);
        
        // Ensure the text is within the image
        if (textOrigin.y < 0) textOrigin.y = bottomRight.y + textSize.height + 2;
        
        cv::putText(image, text, textOrigin, fontFace, fontScale, textColor, thickness);
    }
    Common & instace= Common::getInstance();
    
    //cv::imwrite("res.jpg", image); // Save the modified image
    
    QString fileName = instace.getVideoOut().append(instace.getTimeString() +"置信度:"+ QString::number(boxes->score) + ".jpg");
    bool success = cv::imwrite(fileName.toStdString(), image);
    
    if (success) {
        qInfo() << "车型图片已成功保存至：" << fileName;
    } else {
        qInfo() << "图片保存失败!";
    }
    
}
void HumanDetection::setHuManParameter(QString &uniformColor){
    this->uniformColor=uniformColor;
    
}
//0 人形 1 车形 2 工服
int HumanDetection::findHuManCar(const cv::Mat &source, int res,std::map<int,int>&reMap,QString &sSn, float &heightReference, std::vector<vides_data::ParkingArea> &currentPlate) {
    thread_time.store(QDateTime::currentMSecsSinceEpoch(), std::memory_order_release);

    TCV_CameraStream *stream = TCV_CreateCameraStream();

    ScopeSemaphoreExit streamGuard([this, stream]() {
        isRunning.store(false, std::memory_order_release);

        // 释放相机流
        TCV_ReleaseCameraStream(stream);
    });

    TCV_CameraStreamSetData(stream, source.data, source.cols, source.rows);
    
    TCV_CameraStreamSetRotationMode(stream, TCV_CAMERA_ROTATION_0);
    TCV_CameraStreamSetStreamFormat(stream, TCV_STREAM_BGR);
    
    TCV_HumanDetectorProcessFrame(detector, stream);
    int num = 0;

    if (res == 0x00 || res == 0x02) {
        QStringList colorList = uniformColor.split(',');

        num = TCV_HumanDetectorGetNumOfHuman(detector);
        qInfo() << QString("SN(%1): 获取人形数量:%2").arg(sSn).arg(num);
        if (num == 0) return num; // 无行人检测结果，提前返回
        if(res==0x02 && colorList.size()==0){
            reMap[0x02] = 0; // 未穿工服的行人数量
            reMap[0x00] = num; // 所有满足条件的行人数量
            num = 0;
            return num;
        }
        int count_no_uniform = 0; // 未穿工服的行人数量
        int count_all = 0; // 所有满足条件的行人数量

        std::vector<TCV_ObjectLocation> results(num);
        TCV_HumanDetectorGetHumanLocation(detector, results.data(), num);

        QSet<int> uniformNumbers;
        for (const QString &numStr : colorList) {
            bool ok;
            int num = numStr.toInt(&ok);
            if (ok) {
                uniformNumbers.insert(num);
            }
        }


        for (const auto &person : results) {
            if (std::abs(person.y2 - person.y1) >= heightReference) {
                ++count_all;
                //工服
                if(!uniformNumbers.contains(person.uniform)){
                    vides_data::ParkingArea area;
                    area.topLeftCornerX=person.x1;
                    area.topLeftCornerY=person.y1;
                    area.bottomLeftCornerX=person.x1;
                    area.bottomLeftCornerY=person.y2;
                    area.topRightCornerX=person.x2;
                    area.topRightCornerY=person.y1;
                    area.bottomRightCornerX=person.x2;
                    area.bottomRightCornerY=person.y2;
                    currentPlate.push_back(area);
                    ++count_no_uniform;
                }

            }
        }
        reMap[0x02] = count_no_uniform; // 未穿工服的行人数量
        reMap[0x00] = count_all; // 所有满足条件的行人数量
        num = (res == 0x00) ? count_all : count_no_uniform;

    }
    else if (res == 0x01) {
        num = TCV_HumanDetectorGetNumOfCar(detector);
        if (num == 0) return num; // 无车辆检测结果，提前返回
        
        std::vector<TCV_ObjectLocation> resultCars(num);
        TCV_HumanDetectorGetCarLocation(detector, resultCars.data(), num);
        
        for (const auto &car : resultCars) {
            vides_data::ParkingArea area;
            area.topLeftCornerX=car.x1;
            area.topLeftCornerY=car.y1;
            area.bottomLeftCornerX=car.x1;
            area.bottomLeftCornerY=car.y2;
            area.topRightCornerX=car.x2;
            area.topRightCornerY=car.y1;
            area.bottomRightCornerX=car.x2;
            area.bottomRightCornerY=car.y2;
            currentPlate.push_back(area);
        }
        qInfo() << "findHuManCar 检测到的汽车数量:" << num;
    } else {
        qInfo() << "参数错误";
    }
    return num;
}
