#include "InteractiveFace.h"

InteractiveFace::InteractiveFace(QObject *parent) : QQuickImageProvider(QQuickImageProvider::Image)
{
    initEngine();

    if (hasCamera())
    {
        // initCamera();
    }

    // 图像取1s 10帧
    m_timerId = startTimer(100);
}

bool InteractiveFace::hasCamera()
{
    return !QMediaDevices::videoInputs().isEmpty();
}


InteractiveFace::~InteractiveFace()
{
    destroyEngine();
}

void InteractiveFace::initEngine()
{
    const char* appId = "FTN3G4pk8n2RKwjD955sRapRjbYQFefwhHd4sBZMYEz6";
    const char* sdkKey = "BjJomNU2bQc2SYhT7NNqwvFd9zfc72Q7nneh75r3NT3x";
    const char* licenseFilePath = "./offlineLicense.dat";

    // 超过5次不再尝试获取授权文件
    int iLoopCount = 5;
    do{
        MPChar activeDeviceInfo;
        ASFGetActiveDeviceInfo(&activeDeviceInfo);
        ASF_ActiveFileInfo activeFileInfo;
        MRESULT res = -1;
        if ((res = ASFGetActiveFileInfo(&activeFileInfo)) == MOK)
        {
            qDebug() << "获取版本信息成功";
            break;
        }
        else{
            FileLogger::writeToFile("deviceInfo","ArcSoftDeviceInfo.txt",activeDeviceInfo,FileLogger::WriteMode::OVERWRITE);
            if(res == 0x1601A){

                if((res = ASFOfflineActivation((MPChar)licenseFilePath)) == MOK)
                {
                    qDebug() << "授权成功";
                }
            }
        }
        break;
    }while(iLoopCount--);

    // 初始化引擎
    MRESULT res = ASFInitEngine(ASF_DETECT_MODE_VIDEO,
                                ASF_OP_ALL_OUT,
                                1,
                                ASF_FACE_DETECT | ASF_FACERECOGNITION,
                                &m_engine);

    if (res != MOK)
    {
        qDebug() << " 初始化引擎失败" << res;
    }
}

void InteractiveFace::destroyEngine()
{

}

void InteractiveFace::cameraPlay()
{
    // 如果相机不是播放状态
    if (!m_camera.isActive())
    {
        QCameraDevice cameraDevice = QMediaDevices::defaultVideoInput();
        if (cameraDevice.isNull())
        {
            qWarning() << "系统中没有检测到任何摄像机设备";
            return;
        }

        m_camera.setCameraDevice(cameraDevice);

        // 确保图像宽度是4的倍数(虹软人脸识别要求)
        if (m_camera.cameraFormat().resolution().width() % 4 != 0)
        {
            QList<QCameraFormat> cameraFormats = cameraDevice.videoFormats();
            for (int i = 0; i < cameraFormats.size(); ++i)
            {
                const QCameraFormat &cameraFormat = cameraFormats.at(i);
                if (cameraFormat.resolution().width() % 4 == 0)
                {
                    m_camera.setCameraFormat(cameraFormat);
                    break;
                }
            }
        }

        m_session.setCamera(&m_camera);
        m_session.setVideoSink(&m_videoSink);

        m_camera.start();
    }
}

void InteractiveFace::cameraStop()
{
    if (m_camera.isActive())
    {
        m_camera.stop();
        m_camera.setActive(false);
        m_camera.setCameraDevice(QCameraDevice());

        m_session.setCamera(nullptr);
        m_session.setVideoSink(nullptr);
    }
}


void InteractiveFace::initCamera()
{
    m_camera.setCameraDevice(QMediaDevices::defaultVideoInput());

    QCameraDevice device = QMediaDevices::defaultVideoInput();
    QList<QCameraFormat> formats = device.videoFormats();
    // 选择最适合的格式
    for (const QCameraFormat &format : formats)
    {
        // qDebug() << "fps---" << format.maxFrameRate() << format.resolution().width() << format.resolution().height();
        if (format.maxFrameRate() >= 10.0 && format.resolution().width() % 4 == 0)
        {
            m_camera.setCameraFormat(format);
            break;
        }
    }
    m_session.setCamera(&m_camera);
    m_session.setVideoSink(&m_videoSink);
}

void InteractiveFace::destroyCamera()
{

}

QString InteractiveFace::getImageUrl()
{
    // image://InteractiveFaceImage/(0-9999)
    return QString("image://") +
           QString(INTERACTIVE_FACE_IMAGE_URL) +
           QString("/") +
           // 取随机数，确保图片刷新(Qt机制，两次url地址相同，图片不会显示)
           QString::number(QRandomGenerator::global()->bounded(10000));
}

// 设置图像采集回调
void InteractiveFace::setCameraImageGatherCallBack(QJSValue callback)
{
    m_imageGatherCallback = callback;
}
// 设置发现人脸回调
void InteractiveFace::setCameraImageAppearCallBack(QJSValue callback)
{
    m_imageAppearCallback = callback;
}
// 设置人脸停留回调
void InteractiveFace::setCameraImageRemainCallBack(QJSValue callback)
{
    m_imageRemainCallback = callback;
}

void InteractiveFace::setCameraImageCallBack(QJSValue gatherCallback,
                                             QJSValue appearCallback,
                                             QJSValue remainCallback)
{
    m_imageGatherCallback = gatherCallback;
    m_imageAppearCallback = appearCallback;
    m_imageRemainCallback = remainCallback;
}

void InteractiveFace::setCallBackFaceStatus(QJSValue isAppearCallback)
{
    m_isAppearCallback = isAppearCallback;
}

void InteractiveFace::cameraImagePlay()
{
    if (!hasCamera())
    {
        return;
    }


    if (!m_camera.isActive())
    {
        cameraPlay();
        m_laseEpoch = 0;
        m_laseCount = 0;

        m_FrameId = 0;
    }
}

void InteractiveFace::cameraImageStop()
{
    if (!hasCamera())
    {
        return;
    }

    cameraStop();
}

QImage InteractiveFace::requestImage(const QString &, QSize *, const QSize &)
{
    return m_image;
}

void InteractiveFace::timerEvent(QTimerEvent *event)
{
    if (event->timerId() == m_timerId)
    {
        if (!hasCamera())
        {
            return;
        }

        if (m_camera.isActive())
        {
            QMutexLocker locker(&m_mutex);
            QVideoFrame currentFormat = m_videoSink.videoFrame();

            QImage image;       // 图像
            QPainter painter;   // 画笔

            // 过滤无效帧, 前10帧不做处理
            if(++m_FrameId <= 30)
            {
                m_image = image.copy();
                if (m_imageGatherCallback.isCallable())
                {
                    QJSValueList args;
                    args << getImageUrl();
                    m_imageGatherCallback.call(args);
                }
                return;
            }

            if (currentFormat.isValid())
            {
                if (currentFormat.map(QVideoFrame::ReadOnly))
                {
                    image = currentFormat.toImage();
                    // image = image.scaled(QSize(800, 600), Qt::KeepAspectRatio, Qt::SmoothTransformation);
                }
                currentFormat.unmap();
            }

            if (!image.isNull())
            {
                // image底部框
                painter.begin(&image);
                painter.setRenderHint(QPainter::Antialiasing);
                painter.setFont(QFont("Arial", 24));
                painter.setBrush(QColor(255, 255, 255, 127));
                painter.setPen(Qt::NoPen);
                painter.drawRect(QRect(0, image.height() - 50, image.width(), 50));

                QImage convertedImage = image.convertToFormat(QImage::Format_RGB888);
                ASVLOFFSCREEN offscreen = {0};
                offscreen.u32PixelArrayFormat = ASVL_PAF_RGB24_B8G8R8;
                offscreen.i32Width = convertedImage.width();
                offscreen.i32Height = convertedImage.height();
                offscreen.pi32Pitch[0] = convertedImage.bytesPerLine();
                offscreen.ppu8Plane[0] = (MUInt8*)convertedImage.bits();

                if (offscreen.ppu8Plane[0])
                {
                    if (m_engine != NULL)
                    {
                        ASF_MultiFaceInfo detectedFaces = {0};

                        MRESULT res = ASFDetectFaces(m_engine,
                                                     offscreen.i32Width,
                                                     offscreen.i32Height,
                                                     offscreen.u32PixelArrayFormat,
                                                     offscreen.ppu8Plane[0],
                                                     &detectedFaces);

                        if (res != MOK)
                        {
                            qDebug() << "检测人脸失败" << res;
                        }

                        bool isAppear;
                        // 获取第一个人脸
                        if (res == MOK && detectedFaces.faceNum == 1) {
                            isAppear = true;
                            if (m_laseCount <= 0)
                            {
                                m_laseCount = 1;
                                m_laseEpoch = QDateTime::currentSecsSinceEpoch();
                            }

                            if (m_imageAppearCallback.isCallable())
                            {
                                m_image = image.copy();
                                QJSValueList args;
                                args << getImageUrl();
                                m_imageAppearCallback.call(args);
                            }

                            MRECT mrect = detectedFaces.faceRect[0];

                            qint64 epoch = QDateTime::currentSecsSinceEpoch() - m_laseEpoch;
                            if (epoch <= 1)
                            {
                                painter.setPen(QPen(Qt::blue, 3));
                                painter.drawText(QRect(0, image.height() - 50, image.width(), 50),
                                                 Qt::AlignCenter,
                                                 QString("检测到人脸，即将拍摄").arg(epoch));

                                // 绘制人脸框
                                painter.setPen(QPen(Qt::green, 2));
                                painter.setBrush(Qt::NoBrush);
                                painter.drawRect(QRect(mrect.left,
                                                       mrect.top,
                                                       mrect.right - mrect.left,
                                                       mrect.bottom - mrect.top));
                            }
                            else if (epoch > 1 && epoch <= 4)
                            {
                                painter.setPen(QPen(Qt::blue, 3));
                                painter.drawText(QRect(0, image.height() - 50, image.width(), 50),
                                                 Qt::AlignCenter,
                                                 QString("%1").arg(5 - epoch));

                                // 绘制人脸框
                                painter.setPen(QPen(Qt::green, 2));
                                painter.setBrush(Qt::NoBrush);
                                painter.drawRect(QRect(mrect.left,
                                                       mrect.top,
                                                       mrect.right - mrect.left,
                                                       mrect.bottom - mrect.top));

                            }
                            else if (epoch >= 5)
                            {
                                if (m_imageRemainCallback.isCallable())
                                {
                                    QJSValueList args;
                                    args << getImageUrl();
                                    m_imageRemainCallback.call(args);
                                }
                            }

                        }
                        else if (res == MOK && detectedFaces.faceNum >= 2)
                        {
                            isAppear = true;
                            m_laseCount--;
                            painter.setPen(QPen(Qt::red, 3));
                            painter.drawText(QRect(0, image.height() - 50, image.width(), 50),
                                             Qt::AlignCenter,
                                             QString("请保持单人入镜,请保持光线充足"));
                        }
                        else
                        {
                            isAppear = false;
                            m_laseCount--;
                            painter.setPen(QPen(Qt::red, 3));
                            painter.drawText(QRect(0, image.height() - 50, image.width(), 50),
                                             Qt::AlignCenter,
                                             QString("请保持真人操作,请保持光线充足"));
                        }

                        if (m_isAppearCallback.isCallable())
                        {
                            QJSValueList args;
                            args << isAppear;
                            m_isAppearCallback.call(args);
                        }
                    }
                }

                painter.end();

                m_image = image.copy();

                if (m_imageGatherCallback.isCallable())
                {
                    QJSValueList args;
                    args << getImageUrl();
                    m_imageGatherCallback.call(args);
                }
            }
        }
    }


}

// 获取图像
QImage InteractiveFace::getImage()
{
    QMutexLocker locker(&m_mutex);
    return m_image.copy();
}
