#include "AlgorithmTaskManage.h"

AlgorithmTaskManage::AlgorithmTaskManage():isShuttingDown(false){
    
}

void AlgorithmTaskManage::initialize(int humanDetectionLen, int licensePlateLen, int faceLen,bool first,__uint8_t algorithmPermissions){
    if(first){
        this->humanDetectionLen=humanDetectionLen;
        this->licensePlateLen=licensePlateLen;
        this->faceLen=faceLen;
        semaphore =new QSemaphore(humanDetectionLen);
        plateSemaphore =new  QSemaphore(licensePlateLen);
        faceSemaphore = new QSemaphore(faceLen);
    }else{
        Common & instace= Common::getInstance();
        if (algorithmPermissions == 0x00) {
            this->humanDetectionLen=humanDetectionLen;
            if(semaphore!=nullptr){
                instace.deleteObj(semaphore);
            }
            semaphore =new QSemaphore(humanDetectionLen);
        }
        if(algorithmPermissions == 0x01){
            this->licensePlateLen=licensePlateLen;
            if(plateSemaphore!=nullptr){
                instace.deleteObj(plateSemaphore);
            }
            
            plateSemaphore =new  QSemaphore(licensePlateLen);
            
        }
        if(algorithmPermissions ==0x02){
            this->faceLen=faceLen;
            if(faceSemaphore!=nullptr){
                instace.deleteObj(faceSemaphore);
            }
            faceSemaphore = new QSemaphore(faceLen);
        }
    }
    
}

void AlgorithmTaskManage::initHumanDetectionManage(const QString &modelPaths,
                                                   float carShapeConfidence,int &uniformColor) {
    for (int i = 0; i < humanDetectionLen; ++i) {
        HumanDetection* human=new HumanDetection(modelPaths,carShapeConfidence);
        human->setHuManParameter(uniformColor);
        humanDetections.emplace_back(human);
    }
}
void AlgorithmTaskManage::initLicensePlateManage(const QString &modelPaths,bool is_high,int maxNum,bool useHalf,
                                                 float boxThreshold,float nmsThreshold,float recThreshold){
    for (int i = 0; i < licensePlateLen; ++i) {
        LicensePlateRecognition* licensePlateRecognition=new LicensePlateRecognition(
                    modelPaths,is_high,maxNum,useHalf,boxThreshold,nmsThreshold,recThreshold);
        licensePlateRecognitions.emplace_back(licensePlateRecognition);
    }
    
}
void AlgorithmTaskManage::initFaceReconitionHandle(std::map<QString,QString>&maps,int numberFaces,float confidence){
    for (int i = 0; i < faceLen; ++i) {
        FaceReconitionHandle *faceReconitionHandle=  new FaceReconitionHandle();
        faceReconitionHandle->initSourceImageMap(maps,numberFaces,confidence);
        
        faceReconitionHandles.emplace_back(faceReconitionHandle);
    }
}

void AlgorithmTaskManage::modifyImageFeature(std::map<QString,QString>&maps,int numberFaces,float confidence,bool isNull){
    if (isShuttingDown.load(std::memory_order_acquire)) {
        return ;
    }
    std::lock_guard<std::mutex> lock(mtxFace);
    for (FaceReconitionHandle* face : faceReconitionHandles) {
        face->setImageChanged(true);
        if(isNull){
            face->featureRemove();
        }else {
            face->initSourceImageMap(maps,numberFaces,confidence);
        }
    }
}

AlgorithmTaskManage::~AlgorithmTaskManage(){
    Common & instace= Common::getInstance();
    
    for (auto task:humanDetections) {
        instace.deleteObj(task);
    }
    for (auto plate:licensePlateRecognitions) {
        instace.deleteObj(plate);
    }
    for (auto face:faceReconitionHandles) {
        instace.deleteObj(face);
    }
}

void AlgorithmTaskManage::releaseResources(const vides_data::DetectionParams& params) {
    Common & instance = Common::getInstance();
    
    isShuttingDown.store(true, std::memory_order_release);
    ScopeSemaphoreExit guard([this]() {
        isShuttingDown.store(false, std::memory_order_release);
    });
    __uint8_t algorithmPermissions = params.algorithmPermissions;
    qInfo()<<"修改参数:releaseResources "<<algorithmPermissions;
    int newHumanDetectionLen = params.newHumanDetectionLen;
    int newLicensePlateLen = params.newLicensePlateLen;
    int newFaceLen = params.newFaceLen;
    QString modelPath = params.modelPaths;

    float humanCarShapeConfidence = params.humanCarShapeConfidence;
    int uniformColor = params.uniformColor;
    std::map<QString, QString> faceMaps = params.faceMaps;
    int numberFaces = params.numberFaces;
    float faceConfidence = params.faceConfidence;

    bool high = params.isHigh;
    int maxNum = params.maxNum;
    bool useHalf = params.useHalf;
    float boxThreshold = params.boxConfThreshold;
    float nmsThreshold = params.nmsThreshold;
    float recThreshold = params.recConfidenceThreshold;

    // 穿工服算法参数更新
    if ((algorithmPermissions & 0x01 << 2) != 0) {
        resetSemaphoreAndClearObjects(instance,semaphore, humanDetections, humanDetectionLen);
        initialize(newHumanDetectionLen, newLicensePlateLen, newFaceLen, false, 0x00);
        initHumanDetectionManage(modelPath, humanCarShapeConfidence, uniformColor);
    }
    
    // 人脸算法参数更新
    if ((algorithmPermissions & 0x01 << 1) != 0) {
        resetSemaphoreAndClearObjects(instance,faceSemaphore, faceReconitionHandles, faceLen);
        initialize(newHumanDetectionLen, newLicensePlateLen, newFaceLen, false, 0x02);
        initFaceReconitionHandle(faceMaps, numberFaces, faceConfidence);
    }
    
    // 车牌算法参数更新
    if ((algorithmPermissions & 0x01) != 0) {
        resetSemaphoreAndClearObjects(instance,plateSemaphore, licensePlateRecognitions, licensePlateLen);
        initialize(newHumanDetectionLen, newLicensePlateLen, newFaceLen, false, 0x01);
        initLicensePlateManage(modelPath,high,maxNum,useHalf,boxThreshold,nmsThreshold,recThreshold);
    }
    
}
void* AlgorithmTaskManage::schedulingAlgorithm(int scheType) {
    if (scheType == 0x01) {
        return schedulingAlgorithmTemplate(humanDetections, mtxHuman);
    } else if (scheType == 0x02) {
        return schedulingAlgorithmTemplate(licensePlateRecognitions, mtxLicense);
    } else if (scheType == 0x03) {
        return schedulingAlgorithmTemplate(faceReconitionHandles, mtxFace);
    } else {
        qDebug() << "参数错误";
        return nullptr;
    }
}

void AlgorithmTaskManage::executeFindDoesItExistEmployee(const cv::Mat &source,std::list<vides_data::faceRecognitionResult>&faces,QString sSn){
    if (isShuttingDown.load(std::memory_order_acquire)) {
        return ;
    }
    faceSemaphore->acquire();
    ScopeSemaphoreExit guard([this]() {
        faceSemaphore->release();  // 释放信号量
    });
    auto* selectedFaceReconition = static_cast<FaceReconitionHandle*>(schedulingAlgorithm(0x03));
    if (selectedFaceReconition!=nullptr && !selectedFaceReconition->getImageChanged()) {
        selectedFaceReconition->setIsRunning(true);
        // 调用选定对象的doesItExistEmployee函数
        qDebug() << "人脸识别算法抢到===>sn"<<sSn<<selectedFaceReconition;
        selectedFaceReconition->doesItExistEmployee(sSn,source, faces);
    } else {
        qDebug() << "没有可用的selectedFaceReconition对象可以调度";
        return ;
    }
}


void AlgorithmTaskManage::executeFindlicensePlateNumber(const cv::Mat &source, QString &lpNumber,vides_data::requestLicensePlate &plate,
                                                        qint64 currentTime,QString sSn){
    if (isShuttingDown.load(std::memory_order_acquire)) {
        return ;
    }
    plateSemaphore->acquire();
    ScopeSemaphoreExit guard([this]() {
        plateSemaphore->release();  // 释放信号量
    });
    auto* selectedLicensePlate = static_cast<LicensePlateRecognition*>(schedulingAlgorithm(0x02));
    if (selectedLicensePlate!=nullptr) {
        selectedLicensePlate->setIsRunning(true);
        // 调用选定对象的findHuManCar函数
        qDebug() << "车牌调度算法抢到===>sn"<<sSn<<selectedLicensePlate;
        selectedLicensePlate->licensePlateNumber(source, lpNumber,plate, currentTime);
    } else {
        qDebug() << "没有可用的selectedLicensePlate对象可以调度";
        return ;
    }
}

int AlgorithmTaskManage::executeFindHuManCar(const cv::Mat &source, int res,
                                             std::vector<vides_data::ParkingArea> &currentPlate,std::map<int,int>&resMap,QString sSn,float & heightReference) {
    if (isShuttingDown.load(std::memory_order_acquire)) {
        return -2;
    }
    semaphore->acquire();
    ScopeSemaphoreExit guard([this]() {
        semaphore->release();  // 释放信号量
    });
    auto* selectedHumanDetection = static_cast<HumanDetection*>(schedulingAlgorithm(0x01));
    if (selectedHumanDetection != nullptr ) {
        
        selectedHumanDetection->setIsRunning(true);
        // 调用选定对象的findHuManCar函数
        qDebug() << "人形调度算法抢到===>sn"<<sSn<<"res"<<selectedHumanDetection;
        int detectionResult = selectedHumanDetection->findHuManCar(source, res,resMap, sSn,heightReference,currentPlate);
        return detectionResult;
    } else {
        qDebug() << "没有可用的HumanDetection对象可以调度";
        return -2;
    }
}
