#ifndef FACELIVENESS_H
#define FACELIVENESS_H

#include <QWidget>
#include <QMovie>
#include <QTimer>
#include <thread>
#include <mutex>
#include <opencv2/opencv.hpp>
#include "CLiveViodeProc.h"
#include "CHttpBll.h"

//SHAKE,BLINK,NOD
namespace ACTION_TYPE
{
    const QString AT_BLINK = "BLINK";//眨眼
    const QString AT_SHAKE = "SHAKE";//摇头
    const QString AT_NOD = "NOD";//点头
    const QString AT_FACE_DETECT = "FACE_DETECT";//人脸检测
};

namespace STATUS_TYPE
{
    const QString ST_SUCCESS = "SUCCESS";
    const QString ST_ACTION_FAILED = "ACTION_FAILED";
    const QString ST_NOT_ONESELF = "NOT_ONESELF";
    const QString ST_TIME_OUT = "TIME_OUT";
    const QString ST_ERROR = "ERROR";
};

enum class  FACE_LIVENESS_TYPE
{
    flt_entry_exam = 1,//考前活体
    flt_inprogress  //考中活体
};

struct LivenessVerifyInfo
{
    bool bIsVerify;//检测完成
    QString sActionType;//动作类型
    QString sUrl;
    cv::Mat matImage;
    float fSimilarity;
    int nRealness;
    int nFaceCount;
    bool bPass;
    int nRetryCount;//重试次数
    __int64 nStartTime;//开始时间
    __int64 nEndTime;//结束时间
    int nActionLeftSceonds;//动作剩余时间
    QString sErrorMsg;
    LivenessVerifyInfo()
    {
        bIsVerify = false;
        sActionType = "";
        sUrl = "";
        nRetryCount = 0;
        fSimilarity = 0;
        nRealness = 0;
        nStartTime = 0;
        nEndTime = 0;
        bPass = false;
        nFaceCount = 0;
        nActionLeftSceonds = 0;
        sErrorMsg = "";
    }

    void reset(int actionLeftSceonds)
    {
        bIsVerify = false;
        sUrl = "";
        matImage = cv::Mat();
        bPass = false;
        nRetryCount = 0;
        fSimilarity = 0;
        nRealness = 0;
        nStartTime = 0;
        nEndTime = 0;
        bPass = false;
        nFaceCount = 0;
        sErrorMsg = "";
        nActionLeftSceonds = actionLeftSceonds;
    }

};

namespace Ui {
class faceLiveness;
}

class faceLiveness : public QWidget, ITRTCVideoRenderCallback
{
    Q_OBJECT
signals:
    void faceLivenessFaild();
    void faceLivenessSucceed();
public:
    explicit faceLiveness(FACE_LIVENESS_TYPE livenessType, QWidget *parent = nullptr);
    ~faceLiveness();

private slots:

    void on_btn_fl_startVerify_clicked();

    void onClientExamProcessUploadSign(CClientExamProcessUploadSign processUpload); //文件上传
    void onUploadFileToAliyun(CUploadFileToAliyun uploadFileToAliyun);
    void onSaveFaceLiveVerifyResult(CBaseResponsePackage res);//保存人脸活体验证结果
    void onSaveFaceCompareResult(CBaseResponsePackage res);

    void actionTimer();
    void countdownTimer();
    void on_btn_fl_close_clicked();

private:
    void initUI();
    void initAcionIcon();
    void saveLivenessResult();
    void verifyAction(cv::Mat matImage);
    void onRenderVideoFrame(const char* userId, TRTCVideoStreamType streamType, TRTCVideoFrame* frame);
    bool setBaseImage();
    void saveFaceCampareResult();
    void showVerifyResultUI();

    Ui::faceLiveness *ui;

    std::shared_ptr<QTimer> m_pVideoTimer;
//    std::shared_ptr<QTimer> m_pinitTimer;
//    cv::VideoCapture m_cam;

    std::shared_ptr<QTimer> m_pCloseTimer;

    void threadProc();

    __int64 m_lastFaceTime = 0;
    __int64 m_nStartTime = 0;
    __int64 m_nEndTime = 0;
    int m_nMaxSeconds = 0;

    std::shared_ptr<QTimer> m_ActionTimer;
    std::shared_ptr<QTimer> m_countdownTimer;
    std::shared_ptr<QTimer> m_initTimer;

    std::mutex m_imgMutex;
    std::list<cv::Mat> m_imgList;

    cv::Mat m_nCurImage;
    std::mutex m_imageMutex;

    QList<LivenessVerifyInfo> m_livenessList;
    int m_nCurIndex;
    std::mutex m_livenessListMutex;
    LivenessVerifyInfo m_currentVerifyInfo;
    float m_fMinYaw;
    float m_fMaxYaw;
    QString m_sLivenessStatus;

    std::thread m_thread;
    bool m_bIsRun;

	bool m_bStartCompare = false;
    int m_nRetryCount = 0;
    FACE_LIVENESS_TYPE m_livenessType;

	int m_nFaceDetectDuration = 60;
	int m_nFaceRetryCount = 0;
    int m_nFaceWholeRetryCount = 0;
    const int m_nMaxFaceRetryCount = 3;
    const int m_nMaxFaceWholeRetryCount = 3;
};

#endif // FACELIVENESS_H
