#include "cpowermeterdriver_lp.h"
#include "cpowermeter.h"
#include "logic_compdef.h"
#include "logic_local_def.h"
#include "logic_eap.h"
#include "csystem_external.h"
//LaserPoint
CPowerMeterDriver_lp::CPowerMeterDriver_lp(const QString &name, int32_t id)
    :CPowerMeterDriver(name, id)
{
    m_pSerialPort = new CMSerialPort(QString("COMPORT"), 0);

    m_Variants.add_Variant(Var_LaserPower_MeasRate,
                           QObject::trUtf8("PowerMeasRate"), double(1), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_LaserPower_Temperature,
                           QObject::trUtf8("PowerTemperature"), double(1), false,
                           Variant::TONONE);

    m_lastUsePowermeterTime = QDateTime::currentDateTime();
}

CPowerMeterDriver_lp::~CPowerMeterDriver_lp()
{
    exit_driver();
    if (nullptr != m_pSerialPort) {
        delete m_pSerialPort;
        m_pSerialPort = nullptr;
    }
}

void CPowerMeterDriver_lp::do_msg(int iID, QVariantList& vlInput, V_MsgOutput* pvlOutput)
{
    if (iID == ZERO_POWERMETER) {
        SetZero(POWERMETERHEAD);
        return;
    } else if (iID == FRESHRESULT) {

        int iChildId = vlInput[0].toInt();

        try {
            freshresult(iChildId);
        } catch (...) {
            LOG_ERR("CPowerMeterDriver_lp Freshresult failed. Retry");
            //失败的时候再试一次
            freshresult(iChildId);
        }

        return;
    } else if (iID == GET_TEMPERATURE) {
        int iChildId = vlInput[0].toInt();

        try {
            GetTemperature(iChildId);
        } catch (...) {
            LOG_ERR("CPowerMeterDriver_lp FreshTemperature failed. Retry");
            //失败的时候再试一次
            GetTemperature(iChildId);
        }

        return;
    }
    else if (iID == kPowerMeterCheck) {
        
        check_and_reset_powermeter();
        return;
    }
    else if (iID == kReportCheckResult) {
        report_check_reslt(vlInput[0].toBool());
        return;
    }
    CPowerMeterDriver::do_msg(iID, vlInput, pvlOutput);
}

QDomElement CPowerMeterDriver_lp::WriteConfig(QDomDocument &doc, QDomElement &root)
{
    QDomElement element = CPowerMeterDriver::WriteConfig(doc, root);

    QDomElement ele1 = m_pSerialPort->WriteConfig(doc, element);

    //element.appendChild(ele1);

    return element;
}

int CPowerMeterDriver_lp::ReadConfig(QDomElement &root)
{
    int iIndex = CPowerMeterDriver::ReadConfig(root);

    QDomNodeList List = root.childNodes();
    //int iSizeList=List.size();

    iIndex = m_pSerialPort->ReadConfig(List.at(iIndex).toElement());

    return iIndex;
}

int32_t CPowerMeterDriver_lp::freshresult(int32_t chid)
{

    if(_Sys_Instance_.IsSimulator())
    {
        CPowerMeter* pHead = (CPowerMeter*)FindChannel(chid);
        pHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)->setValue(0.91);
        return 0;
    }

    //LOG(INFO) << "Start Calc Power" <<endl;
    CPowerMeter* pHead = (CPowerMeter*)FindChannel(chid);

    char ch_response[RESPONSE_LEN] = { 0 };

    //默认单位是W
    /*MakeSendCheckComm("VISCA", ch_response);
    int mode = 1;
    try{
    mode = atoi(ch_response);
    }catch(...){
    MQT_THROW_STR(QObject::trUtf8("Powermeter;ComPort Command has illage Send:(%1) Response:(%2)")
    .arg("VISCA").arg(ch_response));
    }*/

    bool isMW = false;
    //if(mode == 3 || mode == 4 || mode == 5){
    //    isMW = true;
    //}

    memset(ch_response, RESPONSE_LEN, 0);

    MakeSendCheckComm("OUTPM", ch_response);
    double power = 0;
    try {
        power = isMW ? (double)atof(ch_response)*0.001 : (double)atof(ch_response);
        //功率系数
        double rate = m_Variants.get_VData(Var_LaserPower_MeasRate)->toDouble();
        power *= rate;
    } catch (...) {
        power = -1;
        pHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)->setValue(power);
        MQT_THROW_CODESTR(ALARM_POWERMETER_COMMUNICATION, QObject::trUtf8("Powermeter;ComPort Command has illage Send:(%1) Response:(%2)")
                          .arg("OUTPM").arg(ch_response));
    }
    //LOG(INFO) << "Start Calc Power" <<endl;
    pHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)->setValue(power);

    return RTN_SUCCESS1;
}

int32_t CPowerMeterDriver_lp::SetZero(int32_t chid)
{
    __LOGINSTANCE__.AddRecord(fmt::format("Zero Powermeter:{}", m_sName.toLocal8Bit().data(), m_iID), "PowerMeter");
    if (_Sys_Instance_.IsSimulator()) {
        CPowerMeter* pHead = (CPowerMeter*)FindChannel(chid);
        pHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)->setValue(0.01);
        return 0;
    }

    CPowerMeter* pHead = (CPowerMeter*)FindChannel(chid);
    pHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)->setValue(0.0);
    char ch_response[RESPONSELENGTH] = { 0 };
    MakeSendCheckComm("ZERO", ch_response);
    if (strcmp(ch_response, "ok")) {
        MQT_THROW_CODESTR(ALARM_POWERMETER_COMMUNICATION, QObject::trUtf8("Powermeter setZero err."));
    }
    return RTN_SUCCESS1;
}

int32_t CPowerMeterDriver_lp::GetTemperature(int32_t chid)
{
    if (_Sys_Instance_.IsSimulator()) {
        //CPowerMeter* pHead=(CPowerMeter*)FindChannel(chid);
        m_Variants.get_VData(Var_LaserPower_Temperature)->setValue(1);
        return 0;
    }

    //CPowerMeter* pHead=(CPowerMeter*)FindChannel(chid);
    m_Variants.get_VData(Var_LaserPower_Temperature)->setValue(0.0);
    char ch_response[RESPONSELENGTH] = { 0 };
    MakeSendCheckComm("TEMP", ch_response);
    double dTemperature = 0;
    try {
        dTemperature = (double)atoi(ch_response) / 10;
    } catch (...) {
        dTemperature = -1;
        //pHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)->setValue(power);
        MQT_THROW_CODESTR(ALARM_POWERMETER_COMMUNICATION, QObject::trUtf8("Powermeter;ComPort Command has illage Send:(%1) Response:(%2)")
                          .arg("TEMP").arg(ch_response));
    }
    //LOG(INFO) << "Start Calc Power" <<endl;
    m_Variants.get_VData(Var_LaserPower_Temperature)->setValue(dTemperature);
    return RTN_SUCCESS1;
}

int32_t CPowerMeterDriver_lp::init_driver()
{
    int ret = 0;
    try {
        if (!_Sys_Instance_.IsSimulator())
            ret = m_pSerialPort->open();
    } catch (QString ex) {

        throw(QString("%1 %2").arg(m_sName).arg(ex));

    }
    return ret;
}

int32_t CPowerMeterDriver_lp::exit_driver()
{
    if (nullptr != m_pSerialPort) {
        m_pSerialPort->close();
    }
    return RTN_SUCCESS1;
}

void CPowerMeterDriver_lp::SendCommand(const char *pCommand, char *pResponse)
{
    QMutexLocker locker(&m_CardMutex);
    int isize = strlen(pCommand);

    try {
        LogRecord(std::string("send:") + pCommand);
        m_pSerialPort->send(pCommand, isize);
        //Sleep(200);
		
        int32_t irtn = m_pSerialPort->wait();
		MSleep(10); 
        int32_t iret = m_pSerialPort->receive(pResponse, irtn);
		if (irtn != iret) {
			qDebug() << "Err:" << irtn <<" " << iret;
		}

		LogRecord(std::string("receive:") + pResponse);
    } catch (const QString& ex) {
        QString info = m_sName + " " + ex;
        LogRecord(info.toLocal8Bit().data());
        MQT_THROW_CODESTR(ALARM_POWERMETER_COMMUNICATION, info);
    }
}

//!
//! \brief CLaserDriver_PI::MakeSendCheckComm
//! \param byCommand
//! 发送的指令
//! \param pSendData
//! 发送的数据
//! \param iDataSSize
//! 发送的数据的大小
//! \param iDataRSize
//! 接收的数据大小
//! \param bWrite
//! 是否写入数据
//! \param pResponse
//! 存储返回数据的指针
//! \param byAddress
//!
void CPowerMeterDriver_lp::MakeSendCheckComm(const char *pSendData, char *pResponse)
{
    char chComm[COMM_LEN] = { 0 };
    chComm[0] = '*';
    int iDataSize = strlen(pSendData);
    memcpy(chComm + 1, pSendData, iDataSize);
    chComm[iDataSize + 1] = ':';

    SendCommand(chComm, (char*)pResponse);

    CheckResponse(pResponse);
}


void CPowerMeterDriver_lp::CheckResponse(char *pResponse)
{

    int iDataRSize = strlen(pResponse);
    if (strlen(pResponse) <= 0) {
		LogRecord("err:recive:0");
        MQT_THROW_CODESTR(ALARM_POWERMETER_COMMUNICATION, QObject::trUtf8("Powermeter ComPort Response Count:%1 Incorrect")
                          .arg(iDataRSize));
    }

    if (pResponse[iDataRSize - 1] != ';') {
		LogRecord(fmt::format("format-err:recive:{}", pResponse));
        MQT_THROW_CODESTR(ALARM_POWERMETER_COMMUNICATION, QObject::trUtf8("Powermeter;ComPort Command has illage Word(%1)")
                          .arg(pResponse));
    }

    pResponse[iDataRSize - 1] = 0;
}


void CPowerMeterDriver_lp::check_and_reset_powermeter()
{
    if (_SysExt_Instance.m_pfnShowPowerMsg) {
        _SysExt_Instance.m_pfnShowPowerMsg(true);
    }
    CPowerMeterDriver_lp* pPowerMeterDriver = GET_CARD(POWERMETERDRIVER,
        CPowerMeterDriver_lp);
    Q_ASSERT(pPowerMeterDriver);

    CPowerMeter* pPowerMeterHead = GET_CHDIRECT(POWERMETERHEAD,
        CPowerMeter);
    Q_ASSERT(pPowerMeterHead);

    pPowerMeterDriver->m_sCheckPowerResult = "";
    pPowerMeterDriver->m_sCurCheckInfo = QObject::tr("Check Power meter zero");
    //如果上次使用功率计时间在10秒内,不用检查功率计状态
    if (pPowerMeterDriver->m_lastUsePowermeterTime.addSecs(10) > QDateTime::currentDateTime()) {
        //不归零，直接使用
        return;
    }

    //功率计归零
    pPowerMeterDriver->freshresult(POWERMETERHEAD);
    double dPower = pPowerMeterHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)
        ->toDouble();



    /*if (!_SysExt_Instance.IsSimulator())
    {
        if (dPower > 0.2)
        {
            MQT_THROW_CODESTR(ALARM_POWERMETER_NOTREADY, QObject::trUtf8("Powermeter check. Powermeter need zero first"));
        }
    }*/

    if (fabs(dPower) > 0.03 || dPower < -0.02) {
        pPowerMeterDriver->m_sCurCheckInfo = QObject::tr("Set Power meter zero");
        pPowerMeterDriver->SetZero(POWERMETERHEAD);
        MSleep(2500);

        pPowerMeterDriver->m_sCurCheckInfo = QObject::tr("Wait Power meter zero");
        for (int i = 0; i < 5; i++) {
            MSleep(1000);
            pPowerMeterDriver->freshresult(POWERMETERHEAD);
            dPower = pPowerMeterHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)
                ->toDouble();
            if (fabs(dPower) < fabs(0.02))
            {
                break;
            }
        }
    }

    __LOGINSTANCE__.AddRecord(fmt::format("After Zero Powermeter Power:{}", dPower), "PowerMeter");

    if (fabs(dPower) > 0.03 || dPower < -0.02) {
        MQT_THROW_CODESTR(ALARM_POWERMETER_NOTREADY, QObject::trUtf8("Powermeter check.Powermeter zero failed"));
    }
}

void CPowerMeterDriver_lp::report_check_reslt(bool bReport)
{
    if (_SysExt_Instance.m_pfnShowPowerMsg) {
        _SysExt_Instance.m_pfnShowPowerMsg(false);
    }
    if (bReport) {
        CPowerMeterDriver_lp* pPowerMeterDriver = GET_CARD(POWERMETERDRIVER,
            CPowerMeterDriver_lp);
        _SysExt_Instance.m_SysMsg.SetMsg(pPowerMeterDriver->m_sCheckPowerResult);
    }
}