#ifndef HUMANDETECTIONMANAGE_H
#define HUMANDETECTIONMANAGE_H
#include "HumanDetection.h"
#include "Common.h"
#include "VidesData.h"
#include "ScopeSemaphoreExit.h"
#include "LicensePlateRecognition.h"
#include "FaceReconitionHandle.h"
#include <QThread>
#include <random>
#include <QSemaphore>
#include <vector>
#include <opencv2/opencv.hpp>
#include <mutex>
#include <condition_variable>
class AlgorithmTaskManage{
public:
    AlgorithmTaskManage();
    ~AlgorithmTaskManage();
    static AlgorithmTaskManage& getInstance()
    {
        static AlgorithmTaskManage instance;
        return instance;
    }
    
    void initialize(int humanDetectionLen, int licensePlateLen, int faceLen,bool first,__uint8_t algorithmPermissions );
    
    void initHumanDetectionManage(const QString &modelPaths,
                                  float carShapeConfidence,int &uniformColor);
    
    void initLicensePlateManage(const QString &modelPaths,bool is_high,int maxNum,bool useHalf,
                                float boxThreshold,float nmsThreshold,float recThreshold);
    
    void modifyImageFeature(std::map<QString,QString>&maps,int numberFaces,float confidence,bool isNull);
    void initFaceReconitionHandle(std::map<QString,QString>&maps,int numberFaces,float confidence);
    
    void *schedulingAlgorithm(int scheType);
    
    
    void releaseResources(const vides_data::DetectionParams& params);
    
    
    
    int executeFindHuManCar(const cv::Mat &source,int res,std::vector<vides_data::ParkingArea> &currentPlate,
                            std::map<int,int>&resMap, QString sSn,float & heightReference);
    
    void executeFindlicensePlateNumber(const cv::Mat &source, QString &lpNumber,vides_data::requestLicensePlate &plate,
                                       qint64 currentTime,QString sSn);
    
    void executeFindDoesItExistEmployee(const cv::Mat &source,std::list<vides_data::faceRecognitionResult>&faces,QString sSn);
    
    
private:
    template<typename T>
    T* schedulingAlgorithmTemplate(std::vector<T*>& objects, std::mutex& mtx) {
        std::lock_guard<std::mutex> lock(mtx);
        qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
        qint64 maxWaitTime = 0;
        std::vector<T*> schedulableObjects;
        for (T* obj : objects) {
            if (obj->getIsRunning()) continue;
            qint64 waitTime = std::abs(currentTime - obj->getThreadTime());
            if (waitTime > maxWaitTime) {
                schedulableObjects.clear();
                schedulableObjects.push_back(obj);
                maxWaitTime = waitTime;
            } else if (waitTime == maxWaitTime) {
                schedulableObjects.push_back(obj);
            }
        }
        if (schedulableObjects.empty()) {
            return nullptr;
        }
        
        if (schedulableObjects.size() == 1) {
            T* selected = schedulableObjects.at(0);
            selected->setIsRunning(true); // 立刻标记为正在运行
            return selected;
        }
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<> dis(0, schedulableObjects.size() - 1);
        T* selected = schedulableObjects[dis(gen)];
        selected->setIsRunning(true); // 立刻标记为正在运行
        return selected;
    }

    template<typename T>
    void resetSemaphoreAndClearObjects(Common& instance, QSemaphore*& semaphore, std::vector<T*>& containers, int len) {
        if (semaphore != nullptr) {
            semaphore->acquire(len);
            for (auto obj : containers) {
                do {
                    if (!obj->getIsRunning()) {
                        instance.deleteObj(obj);
                        break;
                    }
                } while (obj->getIsRunning());
            }
            containers.clear();
            semaphore->release(len);
            instance.deleteObj(semaphore);
        }
    }

    static AlgorithmTaskManage* instance;
    
    std::vector<HumanDetection*>humanDetections;
    
    std::vector<LicensePlateRecognition*>licensePlateRecognitions;
    
    std::vector<FaceReconitionHandle*>faceReconitionHandles;
    
    int humanDetectionLen;
    
    int licensePlateLen;
    
    int faceLen;
    
    QSemaphore *semaphore;
    
    QSemaphore *plateSemaphore;
    
    QSemaphore *faceSemaphore;
    
    std::mutex mtxHuman;
    
    std::mutex mtxLicense;
    
    std::mutex mtxFace;
    
    std::atomic<bool> isShuttingDown;
    
    
};

#endif // HUMANDETECTIONMANAGE_H
