#include "MediaFaceImage.h"
#include "CameraHandle.h"
MediaFaceImage* MediaFaceImage::m_instance = nullptr;  // 初始化指针为空

MediaFaceImage::MediaFaceImage()
{
}

MediaFaceImage::~MediaFaceImage()
{
    XSDK_UnInit();
}

MediaFaceImage* MediaFaceImage::getInstance()
{
    if (m_instance == nullptr)  // 检查指针是否为空
    {
        m_instance = new MediaFaceImage();  // 创建新的实例并指向它
    }
    
    return m_instance;  // 返回指向实例的指针
}
std::map<int,CameraHandle*>MediaFaceImage::getCurrentDevice(){
    return currentDevice;
}

void MediaFaceImage::clearCurrentDevice(int hObject){
    currentDevice.erase(hObject);
}

void MediaFaceImage::setMap(int &key,CameraHandle*value){
    if(currentDevice.count(key)<=0){
        currentDevice.insert(std::make_pair(key, value));
    }
}

static int sdkInitCallback(XSDK_HANDLE hObject, int nMsgId, int nParam1,
                           int nParam2, int nParam3, const char* szString, void* pObject,
                           int64 lParam, int nSeq, void* pUserData, void* pMsg){
    if (pUserData == nullptr) {
        qInfo() << "pUserData 为空";
        return -1;
    }
    switch (nMsgId)
    {
    
    case ESXSDK_ON_DEV_STATE:
    {
        printf("ESXSDK_ON_DEV_STATE[%s]\r\n", nParam1 == 6 ? "ESTATE_DEV_Logined" : "ESTATE_DEV_NetDisConnect");
    }
        break;
    case EXSDK_DATA_FORMATE_FRAME:
        break;
    case EXCMD_ALARM_REQ:
    {
        MediaFaceImage* mediaFaceImage = static_cast<MediaFaceImage*>(pUserData);
        if(mediaFaceImage->getCurrentDevice().count(hObject)>0){
            QString qString(szString);
            CameraHandle* cameraHandle= mediaFaceImage->getCurrentDevice().at(hObject);
            QThreadPool* threadPool = QThreadPool::globalInstance();
            threadPool->setMaxThreadCount(12);
            auto taskCallBack=std::bind(&CameraHandle::callbackFunction, cameraHandle, hObject, qString);
            auto taskRunnable = new TaskRunnable(taskCallBack, hObject,cameraHandle->getChannel(), RunFunction::SdkCallbackFunction);
            threadPool->start(taskRunnable);

        }
    }
        break;
    default:
        break;
    }
    
    return 0;
}
int MediaFaceImage::SdkSearchDevicesSyn(std::map<QString, vides_data::localDeviceStatus *> &devices){
    
    int nMaxCount = 100;
    int nActualCount = 0;
    SXSDK_CONFIG_NET_COMMON* pRet = new SXSDK_CONFIG_NET_COMMON[nMaxCount];
    memset(pRet, 0, sizeof(SXSDK_CONFIG_NET_COMMON) * nMaxCount);
    nActualCount = XSDK_SearchDevicesSyn(pRet, nMaxCount);
    printf("nCount:%d\r\n", nActualCount);
    if (nActualCount <= 0)
    {
        qInfo() << QString("Search no Device");
        delete[] pRet;
        return -1;
    }
    
    if (nActualCount >= 0)
    {
        for (int i = 0; i < nActualCount; i++)
        {
            qInfo() << QString("[%1][IP:%2.%3.%4.%5][SN:%6][Mac:%7]")
                        .arg(i)
                        .arg(pRet[i].HostIP.c[0])
                    .arg(pRet[i].HostIP.c[1])
                    .arg(pRet[i].HostIP.c[2])
                    .arg(pRet[i].HostIP.c[3])
                    .arg(pRet[i].sSn)
                    .arg(pRet[i].sMac);
            vides_data::localDeviceStatus *pDevice=new vides_data::localDeviceStatus();
            pDevice->sSn=QString::fromUtf8(pRet[i].sSn);
            pDevice->HostIP=pRet[i].HostIP;
            pDevice->TCPPort=pRet[i].TCPPort;
            pDevice->HttpPort=pRet[i].HttpPort;
            pDevice->UserName=  QString::fromUtf8(pRet[i].DefaultUser,sizeof(pRet[i].DefaultUser));
            pDevice->password=  QString::fromUtf8(pRet[i].DefaultPwd,sizeof(pRet[i].DefaultPwd));
            devices.insert(std::make_pair(pDevice->sSn, pDevice));
        }
        
        delete[] pRet;
    }
    
    return nActualCount;
}


int MediaFaceImage::SdkInit(QString &szConfigPath, QString &szTempPath) {
    SXSDKInitParam *pParam=new SXSDKInitParam();
    pParam->nLogLevel=8;
    
    QByteArray && byConfigPath=szConfigPath.toLocal8Bit();
    strcpy(pParam->szConfigPath, byConfigPath.data());
    
    QByteArray && byTempPath = szTempPath.toLocal8Bit();
    strcpy(pParam->szTempPath, byTempPath.data());
    
    
    SMsgReceiver sms(nullptr,sdkInitCallback,this);
    pParam->mainMsgCallBack=sms;
    int initResult= XSDK_Init(pParam);
    if(initResult<0){
        qInfo() << "sdk 初始化失败";
        return initResult;
    }
    return initResult;
}
void MediaFaceImage::ParserImageData(const unsigned char* pData, int nDataLen, char* pJpg, int* nJpgLen, char* pJson)
{
    quint32 nPicLen = static_cast<quint32>(pData[0]) | (static_cast<quint32>(pData[1]) << 8) | (static_cast<quint32>(pData[2]) << 16) | (static_cast<quint32>(pData[3]) << 24);
    qInfo() << "nPicLen =" << nPicLen;
    *nJpgLen = static_cast<int>(nPicLen);
    memcpy(pJpg, (pData + 32), *nJpgLen);
    const unsigned char* pInfoHead = nullptr;
    for (int i = nDataLen - 2; i > -1; i--)
    {
        if (pData[i] == 0xff && pData[i + 1] == 0xd9)
        {
            pInfoHead = pData + i;
            break;
        }
    }
    if (pInfoHead != nullptr)
    {
        strcpy(pJson, reinterpret_cast<const char*>(pInfoHead + 2));
    }
}

int MediaFaceImage::AbFile(const char* pFileName, const void* pData, int nLength) {
    if (pData == NULL || nLength <= 0) {
        return -2;
    }
    
    FILE* fp = fopen(pFileName, "ab+");
    if (fp == NULL) {
        // 文件打开失败
        return -1;
    }
    
    size_t written = fwrite(pData, 1, nLength, fp);
    if (written != nLength) {
        // 写入的数据长度与预期不符
        fclose(fp);
        return -3;
    }
    
    fflush(fp); // 确保数据被写入
    fclose(fp);
    return 0;
}


int MediaFaceImage::ToFile(const char* pFileName, const void* pData, int nLength)
{
    if (pData == NULL || nLength <= 0)
    {
        // 数据指针为空或长度不正确
        return -2;
    }
    
    FILE* fp = fopen(pFileName, "wb");
    if (fp == NULL)
    {
        // 文件打开失败
        return -1;
    }
    
    size_t written = fwrite(pData, 1, nLength, fp);
    if (written != nLength)
    {
        // 写入的数据长度与预期不符
        fclose(fp);
        return -3;
    }
    
    fflush(fp); // 确保数据被写入
    fclose(fp);
    return 0;
}
//int MediaFaceImage::FaceImageCallBack(XSDK_HANDLE hMedia, int nChannel, cv::Mat &image) {
//    const int BufferSize = 1024 * 1024 * 2; // 定义缓冲区大小
//    image.release();
//    // 使用智能指针管理资源
//    std::unique_ptr<unsigned char[]> pOutBuffer(new unsigned char[BufferSize]);
//    int pInOutBufferSize = 0;

//    int ret = XSDK_DevSnapSyn(hMedia, nChannel, "", pOutBuffer.get(), &pInOutBufferSize);

//    if (ret < 0 || pInOutBufferSize <= 0) {
//        qInfo() << "同步设备端抓图失败";
//        return -1;
//    }

//    // 使用vector管理buffer
//    std::vector<uchar> buffer(pInOutBufferSize);
//    memcpy(buffer.data(), pOutBuffer.get(), pInOutBufferSize);
//    image =std::move(cv::imdecode(buffer, cv::IMREAD_UNCHANGED));

//    return pInOutBufferSize; // pOutBuffer由智能指针管理，此处无需手动释放
//}

int MediaFaceImage::FaceImageCallBack(XSDK_HANDLE hMedia, int nChannel, cv::Mat &image) {
    const int BufferSize = 1024 * 1024 * 2; // 缓冲区大小
    image.release();                        // 释放之前的图像
    std::unique_ptr<unsigned char[]> pOutBuffer(new unsigned char[BufferSize]); // 智能指针管理内存
    int pInOutBufferSize = 0;

    int ret = XSDK_DevSnapSyn(hMedia, nChannel, "", pOutBuffer.get(), &pInOutBufferSize);
    if (ret < 0 || pInOutBufferSize <= 0) {
        qInfo() << "同步设备端抓图失败";
        return -1;
    }

    // 使用 std::vector 管理缓冲区数据
    std::vector<uchar> buffer(pInOutBufferSize);
    memcpy(buffer.data(), pOutBuffer.get(), pInOutBufferSize);

    try {
        cv::Mat decodedImage = cv::imdecode(buffer, cv::IMREAD_UNCHANGED);
        if (decodedImage.empty()) {
            qInfo() << "图像解码失败";
            return -1;
        }
        image = std::move(decodedImage);
    } catch (const cv::Exception& e) {
        qInfo() << "图像解码过程中捕获异常：" << e.what();
        return -1;
    }

    return pInOutBufferSize;
}

int MediaFaceImage::CameraImage(XSDK_HANDLE hMedia,int nChannel,std::vector<uchar> &buffer){
    static const int BufferSize = 1024 * 1024 * 2; // 2MB buffer size
    static unsigned char pOutBuffer[BufferSize];

    // 初始化为0，用于接收实际填充的大小
    int pInOutBufferSize = 0;

    // 尝试从设备获取快照数据
    int ret = XSDK_DevSnapSyn(hMedia, nChannel, "", pOutBuffer, &pInOutBufferSize);
    if (ret < 0 || pInOutBufferSize <= 0) {
        qInfo() << "同步设备端抓图失败";
        return -1; // 返回-1表示失败
    }

    // 用pOutBuffer里的数据初始化vector，复制数据到vector中
    buffer = std::vector<uchar>(pOutBuffer, pOutBuffer + pInOutBufferSize);

    // 返回实际填入Vector的数据大小
    return pInOutBufferSize;
}

