#include "VrEyeDevice.h"
#include "VrError.h"
#include "VrSimpleLog.h"

#include <functional>

CVrEyeDevice::CVrEyeDevice()
{
}

CVrEyeDevice::~CVrEyeDevice()
{

}

int CVrEyeDevice::InitDevice()
{
    return CVrEyeCommon::GetInstance()->InitDevice();
}

int CVrEyeDevice::OpenDevice(const char* sIP, VzNL_OnNotifyStatusCBEx fNotify, void *param)
{
    int nErrCode = SUCCESS;
    // 搜索设备
    VzNL_ResearchDevice(keSearchDeviceFlag_EthLaserRobotEye);

    // 获取搜索到的设备
    SVzNLEyeCBInfo* pCBInfo = nullptr;
    int nCount = 0;
    nErrCode = VzNL_GetEyeCBDeviceInfo(nullptr, &nCount);
    if (0 != nErrCode)
    {
        return ERR_CODE(nErrCode);
    }

    if(0 == nCount)
    {
        return ERR_CODE(DEV_NOT_FIND);
    }

    pCBInfo = new SVzNLEyeCBInfo[nCount];
    VzNL_GetEyeCBDeviceInfo(pCBInfo, &nCount);

    SVzNLOpenDeviceParam sVzNlOpenDeviceParam;
    if(nullptr == sIP)
    {
        m_pHandle = VzNL_OpenDevice(&pCBInfo[0], &sVzNlOpenDeviceParam, &nErrCode);
    }
    else
    {
        for(int i = 0; i < nCount; i++)
        {
            if(strcmp(pCBInfo[i].byServerIP, sIP) == 0)
            {
                m_pHandle = VzNL_OpenDevice(&pCBInfo[i], &sVzNlOpenDeviceParam, &nErrCode);
                break;
            }
        }
    }

    if(nullptr == m_pHandle)
    {
        delete[] pCBInfo;
        return ERR_CODE(DEV_OPEN_ERR);
    }

    if(0 != nErrCode)
    {
        delete[] pCBInfo;
        return ERR_CODE(nErrCode);
    }


    m_sEeyCBDeviceInfo.sEyeCBInfo.nSize = sizeof(SVzNLEyeDeviceInfoEx);
    VzNL_GetDeviceInfo(m_pHandle, (SVzNLEyeCBInfo *)(&m_sEeyCBDeviceInfo));
    LOG_DEBUG("video res : w-%u h-%u", m_sEeyCBDeviceInfo.sVideoRes.nFrameWidth, m_sEeyCBDeviceInfo.sVideoRes.nFrameHeight);
    //启用RGBD
    VzNL_EnableRGB(m_pHandle, VzTrue);
    //配置RGBD参数
    VzNL_BeginDetectLaser(m_pHandle);
    VzNL_EnableSwingMotor(m_pHandle, VzTrue);
    VzNL_EnableLaserLight(m_pHandle, VzFalse);

    //设置停止位置
    SVzSwingMotorDevInfo swingMotorDevInfo{};
    VzNL_GetSwingMotorInfo(m_pHandle, &swingMotorDevInfo);
    //            VzNL_SetSwingStopAngle(m_pHandle, swingMotorDevInfo.fMotorMaxAngle / 2.f);

    // 版本信息打印
    unsigned int versionCode = VzNL_GetSwingVersionCode(m_pHandle);
    LOG_DEBUG("swing versiong : %u", versionCode);

    int nnnRet = VzNL_SetEthSendDataLength(m_pHandle, 1024);
    LOG_DEBUG("SenddataLen ret : %d", nnnRet);

    //白平衡
    VzBool  bEnable = VzNL_IsEnableRGBAWB(m_pHandle, &nnnRet);
    LOG_DEBUG("EnableRGBAWB : %d [%d]", bEnable, nnnRet);

    bEnable = VzNL_IsEnableRGBAutoExpose(m_pHandle, &nnnRet);
    LOG_DEBUG("RGBAutoExpose : %d [%d]", bEnable, nnnRet);
    if(VzFalse == bEnable)
    {
        nnnRet = VzNL_EnableRGBAutoExpose(m_pHandle, VzTrue);
        LOG_DEBUG("EnableRGBAutoExpose [%d]", nnnRet);
    }

    float  exposeThres = VzNL_GetRGBAutoExposeThres(m_pHandle, &nnnRet);
    LOG_DEBUG("RGBAutoExposeThres : %f [%d]", exposeThres, nnnRet);

    //设置回调
    VzNL_SetDeviceStatusNotifyEx(m_pHandle,fNotify, param);

    //获取内部接口类
    VzNL_QueryDeviceData(m_pHandle, (void **)(&m_pDeviceCore));

    delete[] pCBInfo;
    
    return SUCCESS;
}

int CVrEyeDevice::GetVersion(SVzNLVersionInfo &sVersionInfo)
{
    if(!m_pHandle) return ERR_CODE(DEV_NO_OPEN);
    return VzNL_GetVersion(m_pHandle, &sVersionInfo);
}

int CVrEyeDevice::GetDevInfo(SVzNLEyeDeviceInfoEx &sDeviceInfo)
{
    if(!m_pHandle) return ERR_CODE(DEV_NO_OPEN);
    memcpy(&sDeviceInfo, &m_sEeyCBDeviceInfo, sizeof(SVzNLEyeDeviceInfoEx));
    return SUCCESS;
}

int CVrEyeDevice::CloseDevice()
{
    int nErrCode = SUCCESS;
    if(!m_pHandle) return ERR_CODE(DEV_NO_OPEN);
    VzNL_EndDetectLaser(m_pHandle);
    nErrCode = VzNL_CloseDevice(m_pHandle);
    if(0 == nErrCode)
    {
        m_pHandle = nullptr;
    }
    return nErrCode;
}

int CVrEyeDevice::StartDetect(VzNL_AutoOutputLaserLineExCB fCallFunc, void *param)
{
    int nErrCode = SUCCESS;
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    nErrCode = VzNL_StartAutoDetectEx(m_pHandle,keResultDataType_PointXYZRGBA, keFlipType_None, fCallFunc, param);
    return nErrCode;
}

bool CVrEyeDevice::IsDetectIng()
{
    return false;
}

int CVrEyeDevice::StopDetect()
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    return VzNL_StopAutoDetect(m_pHandle);
}

int CVrEyeDevice::SetDetectROI(SVzNLRect &leftROI, SVzNLRect &rightROI)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    int nErrCode = SUCCESS;

    return nErrCode;
}

int CVrEyeDevice::GetDetectROI(SVzNLRect &leftROI, SVzNLRect &rightROI)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    int nErrCode = SUCCESS;

    return nErrCode;
}

int CVrEyeDevice::SetEyeExpose(unsigned int &exposeTime)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    return VzNL_ConfigEyeExpose(m_pHandle, keVzNLExposeMode_Fix, exposeTime);
}

int CVrEyeDevice::GetEyeExpose(unsigned int &exposeTime)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    EVzNLExposeMode peExposeMode;
    return VzNL_GetConfigEyeExpose(m_pHandle, &peExposeMode, &exposeTime);
}

int CVrEyeDevice::SetEyeGain(unsigned int &gain)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    int nRet = VzNL_SetCameraGain(m_pHandle, keEyeSensorType_Left, gain);
    nRet |= VzNL_SetCameraGain(m_pHandle, keEyeSensorType_Right, gain);
    return nRet;
}

int CVrEyeDevice::GetEyeGain(unsigned int &gain)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    return VzNL_GetCameraGain(m_pHandle, keEyeSensorType_Left, reinterpret_cast<unsigned short *>(&gain));
}

int CVrEyeDevice::SetFrame(int &frame)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    return VzNL_SetFrameRate(m_pHandle, frame);
}

int CVrEyeDevice::GetFrame(int &frame)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    return VzNL_GetFrameRate(m_pHandle, reinterpret_cast<int *>(&frame));
}

bool CVrEyeDevice::IsSupport()
{
    if(!m_pHandle) return false;

    int nRet = 0;
    VzBool bSupport = VzNL_IsSupportRGBCamera(m_pHandle, &nRet);
    return VzTrue == bSupport;
}

int CVrEyeDevice::SetRGBDExposeThres(float &value)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    return VzNL_SetRGBAutoExposeThres(m_pHandle, value);
}

int CVrEyeDevice::GetRGBDExposeThres(float &value)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    int nRet = 0;
    value = VzNL_GetRGBAutoExposeThres(m_pHandle, &nRet);
    return nRet;
}

int CVrEyeDevice::SetFilterHeight(double &dHeight)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    return VzNL_ConfigLaserLineFilterHeight(m_pHandle, dHeight);
}

int CVrEyeDevice::GetFilterHeight(double &dHeight)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    return VzNL_GetLaserLineFilterHeight(m_pHandle, &dHeight);
}

int CVrEyeDevice::GetSwingSpeed(float &fSpeed)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    return VzNL_GetSwingAngleSpeed(m_pHandle, &fSpeed);
}

int CVrEyeDevice::SetSwingSpeed(float &fSpeed)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    return VzNL_SetSwingAngleSpeed(m_pHandle, fSpeed);
}

int CVrEyeDevice::SetSwingAngle(float &fMin, float &fMax)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    return VzNL_SetSwingMotorAngle(m_pHandle, fMin, fMax);
}

int CVrEyeDevice::GetSwingAngle(float &fMin, float &fMax)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    return VzNL_GetSwingMotorAngle(m_pHandle, &fMin, &fMax);
}

int CVrEyeDevice::SetWorkRange(double &nMin, double &nMax)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    return VzNL_SetSwingMotorWorkRange(m_pHandle, nMin, nMax);
}

int CVrEyeDevice::GetWorkRange(double &dMin, double &dMax)
{
    if(!m_pHandle) return ERRCODE(DEV_NO_OPEN);
    return VzNL_GetSwingMotorWorkRange(m_pHandle, &dMin, &dMax);
}

// 初始化对象
int IVrEyeDevice::CreateObject(IVrEyeDevice** ppEyeDevice)
{
    CVrEyeDevice* p = new CVrEyeDevice;
    *ppEyeDevice = p;
    return 0;
}
