#include "claserpath.h"
#include "logic_local_def.h"
#include "csystem_external.h"
#include "macro_def.h"
CLaserPath::CLaserPath(const QString& name, int32_t id)
    :CChannel(name, id)
{
    m_Variants.add_Variant(Var_LaserPath_PChangeAngle_ID,
                           QObject::trUtf8("PChangeAngle"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_PowerMaxAngle_ID,
                           QObject::trUtf8("PowerMaxAngle"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_DIndexZeroAngle_ID,
                           QObject::trUtf8("DIndexZeroAngle"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_DIndexMax_ID,
                           QObject::trUtf8("DIndex_Max"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_5050ZeroAngle_ID,
                           QObject::trUtf8("ZeroAngle5050"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_5050CalcuStep_ID,
                           QObject::trUtf8("CalcuStep5050"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_SIndexZeroAngle_ID,
                           QObject::trUtf8("SIndexZeroAngle"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_SIndexMax_ID,
                           QObject::trUtf8("SIndexMax"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_HairOffsetThres_ID,
                           QObject::trUtf8("HairOffsetThres"), double(0), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_LaserOffset,
                           QObject::trUtf8("HairOffset"), double(0), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_LaserPath_Use5050Vector_ID,
                           QObject::trUtf8("UsePowerAngleVector"), false, false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_UseFixSetting,
                           QObject::trUtf8("UseFixSetting"), false, false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_Angle1,
                           QObject::trUtf8("FixAngle1"), double(1), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_Angle2,
                           QObject::trUtf8("FixAngle2"), double(15), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_LaserPath_UseFixPowerSetting,
                           QObject::trUtf8("UseFixPowerSetting"), false, false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_PowerSet,
                           QObject::trUtf8("FixPowerAngle"), double(0), false,
                           Variant::TOXML);

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


    //频率和Epulse控制
    m_Variants.add_Variant(Var_LaserPath_UseFixFreq,
                           QObject::trUtf8("UseFixFreq"), false, false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_FixFreqValue,
                           QObject::trUtf8("FixFreqValue"), int(50), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_LaserPath_UseFixEpulse,
                           QObject::trUtf8("UseFixEpulse"), false, false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_FixEpulseValue,
                           QObject::trUtf8("FixEpulseValue"), int(100), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_UseFixGripper,
                           QObject::trUtf8("UseFixGripper"), false, false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_LaserPath_FixGripperPos,
                           QObject::trUtf8("FixGripperPos"), int(100), false,
                           Variant::TOXML);


#if __SIMULATOR__
    m_Variants.get_VData(Var_LaserPath_UseFixSetting)->setValue(true);
    m_Variants.get_VData(Var_LaserPath_UseFixPowerSetting)->setValue(true);
#endif
    m_LaserOffsetY = 0;
}

CLaserPath::~CLaserPath()
{

}

QDomElement CLaserPath::WriteConfig(QDomDocument& doc, QDomElement& root)
{
    QDomElement elem = CChannel::WriteConfig(doc, root);
    //卡抓数据
    if (m_iID == LASERPATH_D_WIDE)
    {
        WriteBeamPosMapCsv();
    }
#ifdef __LOWK_SOLUTION__
    if (m_iID != LASERPATH_D_WIDE)
    {
        WriteDIndexParamVectorCsv();
        WriteOffsetVector();
    }
#endif

    if (m_iID != LASERPATH_S_NARROW)
    {
        WritePowerPosMap();
        WritePowerPosMapCsv();
    }
    return elem;
}

int CLaserPath::ReadConfig(QDomElement& root)
{
    int iIndex = CChannel::ReadConfig(root);

    //读取功率宽度
    if (m_iID == LASERPATH_D_WIDE || m_iID == LASERPATH_L_NARROW)
    {
        ReadBeamPosMapCsv();
    }

    //读取光路控制宽度的参数
#ifdef __LOWK_SOLUTION__
    if (m_iID == LASERPATH_D_NARROW)
    {
        //读取关联的dWidth 对应的参数
        ReadDIndexParamVectorCsv();
        ReadOffsetVector();
    }
#endif

    //读取功率参数
    ReadPowerPosMap();
    return iIndex;
}

bool CLaserPath::ReadDIndexParamVectorCsv()
{
    //QString strPath = CMakePath::make_config_path(m_sName + "_WidthParam.csv");
    QString strPath = GetFilePath("WidthParam.csv");

    QFile file(strPath);
    if (!file.open(QIODevice::ReadOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }
    m_vDIndexParam.clear();
    QTextStream stream(&file);
    while (!file.atEnd())
    {
        QString sLine = file.readLine();
        if (sLine.isEmpty())
        {
            continue;
        }

        QStringList paramList = sLine.split(",");
        if (paramList.count() < 3)
        {
            continue;
        }

        QPair<int, DIndexParam> pairAngle;
        pairAngle.first = paramList[0].toInt();
        pairAngle.second.dAngle1 = paramList[1].toDouble();
        pairAngle.second.dAngle2 = paramList[2].toDouble();

        m_vDIndexParam.push_back(pairAngle);
    }

    file.close();

    return true;
}

void CLaserPath::WriteDIndexParamVectorCsv()
{
    //QString strPath = CMakePath::make_config_path(m_sName + "_WidthParam.csv");
    QString strPath = GetFilePath("WidthParam.csv");

    QFile file(strPath);
    if (!file.open(QIODevice::WriteOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }
    QTextStream stream(&file);
    /*m_vPowerPos.clear();
    for(int i = 0; i < 10; i++) {
        DIndexParam indexParam;
        indexParam.dAngle1 = 0.1 * i;
        indexParam.dAngle2 = 0.2 * i;
        QPair<int, DIndexParam> param;
        param.first = i;
        param.second = indexParam;
        m_vDIndexParam.push_back(param);
    }*/

    for (auto iter : m_vDIndexParam)
    {
        stream << iter.first << "," << iter.second.dAngle1
            << "," << iter.second.dAngle2 << "\n";
    }
    file.flush();
    file.close();
}

bool CLaserPath::ReadPowerPosCsv()
{
    QString strPath = CMakePath::make_config_path(m_sName + "_LaserCaliData.csv");

    QFile file(strPath);
    if (!file.open(QIODevice::ReadOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }
    m_vPowerPos.clear();
    QTextStream stream(&file);
    while (!file.atEnd())
    {
        QString sLine = file.readLine();
        if (sLine.isEmpty())
        {
            continue;
        }

        QStringList paramList = sLine.split(",");
        if (paramList.count() < 3)
        {
            continue;
        }

        PowerParamIndex powerParam;
        powerParam.dIndex = paramList[0].toDouble();
        powerParam.dPower = paramList[1].toDouble();
        powerParam.dPower_RT = paramList[2].toDouble();

        m_vPowerPos.push_back(powerParam);
    }

    file.close();

    return true;
}

void CLaserPath::WritePowerPosVectorCsv()
{
    //QString strPath = CMakePath::make_config_path(m_sName + "_LaserCaliData.csv");
    QString  strPath = GetFilePath("LaserCaliData.csv");
    QFile file(strPath);
    if (!file.open(QIODevice::WriteOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }
    m_vPowerPos.clear();
    QTextStream stream(&file);
    for (int i = 0; i < 10; i++)
    {
        PowerParamIndex powerParam;
        powerParam.dIndex = 0.1 * i;
        powerParam.dPower = 0.2 * i;
        powerParam.dPower_RT = 0.3 * i;

        m_vPowerPos.push_back(powerParam);
    }

    for (auto iter : m_vPowerPos)
    {
        stream << iter.dIndex << "," << iter.dPower << "," << iter.dPower_RT << "\n";
    }
    file.flush();
    file.close();
}

//double CLaserPath::CalcuSIndexAngle(double dSIndex)
//{
//    Q_ASSERT(m_iID == LASERPATH_D_WIDE);
//    double dSingleIndexMax =
//        m_Variants.get_VData(Var_LaserPath_SIndexMax_ID)->toDouble();
//    double dSingleIndexZeroOffsetAngle =
//        m_Variants.get_VData(Var_LaserPath_SIndexZeroAngle_ID)->toDouble();
//    if(DEQUAL0(dSingleIndexMax)) {
//        MQT_THROW_STR(QObject::trUtf8("SingleIndexMax is Zero"));
//    }
//    return DEG(asin(dSIndex / dSingleIndexMax)) + dSingleIndexZeroOffsetAngle;
//}

void CLaserPath::ReadOffsetVector()
{
    return;
    m_vOffset.clear();
    //QString strPath = CMakePath::make_config_path(m_sName + "_LaserOffset.ldf");
    QString strPath = GetFilePath("LaserOffset.ldf");
    QFile file(strPath);
    if (!file.open(QIODevice::ReadOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }
    QDataStream stream(&file);
    int32_t iSize = 0;
    stream >> iSize;
    for (int i = 0; i < iSize; i++)
    {
        QPair<CMPathIndex, double> pairAngle;
        stream >> pairAngle.first.iFirstIndex;
        stream >> pairAngle.first.iSecondIndx;
        stream >> pairAngle.second;
        m_vOffset.push_back(pairAngle);
    }
}

void CLaserPath::WriteOffsetVector()
{
    //QString strPath = CMakePath::make_config_path(m_sName + "_LaserOffset.ldf");
    QString strPath = GetFilePath("LaserOffset.ldf");
    QFile file(strPath);
    if (!file.open(QIODevice::WriteOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }
    QDataStream stream(&file);
    int32_t iSize = m_vOffset.size();
    stream << iSize;
    for (int i = 0; i < iSize; i++)
    {
        QPair<CMPathIndex, double>& pairAngle = m_vOffset[i];
        stream << pairAngle.first.iFirstIndex;
        stream << pairAngle.first.iSecondIndx;
        stream << pairAngle.second;
    }
}


int CLaserPath::SetOffset(double dDIndex, double dSIndex, double dOffset)
{
    if (m_iID == LASERPATH_D_NARROW)
    {
        dSIndex = 0;
    }
    int iSize = m_vOffset.size();
    QPair<CMPathIndex, double> Offset;
    Offset.first.iFirstIndex = int(dDIndex * 1000);
    Offset.first.iSecondIndx = int(dSIndex * 1000);
    Offset.second = dOffset;
    if (!Offset.first.iFirstIndex && !Offset.first.iSecondIndx)
    {
        return 0;
    }
    int i = 0;
    if (iSize)
    {
        for (i = 0; i < iSize; i++)
        {
            if (m_vOffset[i].first.iFirstIndex == Offset.first.iFirstIndex &&
                m_vOffset[i].first.iSecondIndx > Offset.first.iSecondIndx)
            {
                m_vOffset.insert(m_vOffset.begin() + i, Offset);
                break;
            }

            else if (m_vOffset[i].first.iFirstIndex > Offset.first.iFirstIndex)
            {
                m_vOffset.insert(m_vOffset.begin() + i, Offset);
                break;
            }
            else if (m_vOffset[i].first == Offset.first)
            {
                m_vOffset[i].second = Offset.second;
                break;
            }
        }
    }
    if (i == iSize)
    {
        m_vOffset.push_back(Offset);
    }
    _Sys_Instance_.EvtLog(QString::fromUtf8("HA"),
                          QObject::trUtf8("%4:DoubleIndex:%1mm,SingleIndex:%2mm,Offset:%3mm")
                          .arg(dDIndex)
                          .arg(dSIndex)
                          .arg(dOffset)
                          .arg(m_sName));
    return 0;
}


int CLaserPath::SetOffset(double dOffset)
{
    //m_LaserOffsetY = dOffset;
    m_Variants.get_VData(Var_Process_LaserOffset)->setValue(dOffset);
    return 0;
}

int CLaserPath::GetOffset(double dDIndex, double dSIndex, double& dOffset)
{
    //Narrow光没有挡光板宽度
    if (m_iID == LASERPATH_D_NARROW)
    {
        dSIndex = 0;
    }
    dOffset = 0;
    int iSize = m_vOffset.size();
    CMPathIndex Index(dDIndex * 1000, dSIndex * 1000);
    if ((Index.iFirstIndex == 0 && Index.iSecondIndx == 0) || !iSize)
    {
        return 0;
    }
    for (int i = 0; i < iSize; i++)
    {
        if (Index == m_vOffset[i].first)
        {
            dOffset = m_vOffset[i].second;
            return 0;
        }
    }
    return 0;
}

int CLaserPath::GetOffset(double& dOffset)
{
    //dOffset = m_LaserOffsetY;
    dOffset = m_Variants.get_VData(Var_Process_LaserOffset)->toDouble();
    return 0;
}
//
//int CLaserPath::AddDIndexParamToVector(double dDIndex, double dAngle)
//{
//    int iWidth = dDIndex * 1000;
//    int iSize = m_vDIndexParam.size();
//    QPair<int, DIndexParam> PairCur;
//    PairCur.first = iWidth;
//    PairCur.second.dAngle1 = dAngle;
//    PairCur.second.dAngle2 = CalcuDIndexAngle(dDIndex);
//    if(!iSize) {
//        m_vDIndexParam.push_back(PairCur);
//        return 0;
//    }
//    if(iWidth > m_vDIndexParam[iSize - 1].first) {
//        MQT_THROW_STR(QObject::trUtf8("width:%.3f>Dual Max:%.3f")
//                      .arg(iWidth / 1000.0)
//                      .arg(m_vDIndexParam[iSize - 1].first / 1000.0));
//
//    }
//    for(int i = 0; i < iSize; i++) {
//        QPair<int, DIndexParam>& Pair = m_vDIndexParam[i];
//        if(PairCur.first == Pair.first) {
//            Pair.second.dAngle1 = PairCur.second.dAngle1;
//            Pair.second.dAngle2 = PairCur.second.dAngle2;
//            return 0;
//        }
//        if(PairCur.first < Pair.first) {
//            m_vDIndexParam.insert(m_vDIndexParam.begin() + i, PairCur);
//            return 0;
//        }
//    }
//    return 0;
//}

double CLaserPath::GetBeamPos(double dBeamWidth)
{
    if (m_iID != LASERPATH_D_WIDE)
    {
        MQT_THROW_STR(QObject::trUtf8("Only D_WIDE has BeamWidth"));
        return 0;
    }

    if (m_Variants.get_VData(Var_LaserPath_UseFixGripper)->toBool()
        && _Sys_Instance_.m_Variants.get_VData(Var_Enable_FixLaserPathAngle)->toBool())
    {
        double dPos = m_Variants.get_VData(Var_LaserPath_FixGripperPos)->toInt();
        return dPos;
    }

    LPATHBEAMPOSMAP::iterator  ii = m_mBeamPos.find(int(dBeamWidth * 1000));
    if (ii != m_mBeamPos.end())
    {
        return (*ii);
    }
#ifdef __SIMULATOR__
    return 0;
#endif // __SIMULATOR__
    MQT_THROW_STR(QObject::trUtf8("BeamWidth Pos not Find"));
    return 0;
}

void CLaserPath::AddToBeamPosMap(double dBeamWidth, double dPos)
{
    m_mBeamPos[int(dBeamWidth * 1000)] = dPos;
}

void CLaserPath::DelFromBeamPosMap(double dBeamWidth)
{
    LPATHBEAMPOSMAP::iterator  ii = m_mBeamPos.find(int(dBeamWidth * 1000));
    if (ii != m_mBeamPos.end())
    {
        m_mBeamPos.erase(ii);
    }
}

void CLaserPath::WriteBeamPosMapCsv()
{
    //QString strPath = CMakePath::make_config_path(m_sName + "_LaserBeamWidth.csv");
    QString strPath = GetFilePath("LaserBeamWidth.csv");
    QFile file(strPath);
    if (!file.open(QIODevice::WriteOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }

    QTextStream stream(&file);
    for (auto iter = m_mBeamPos.begin(); iter != m_mBeamPos.end(); iter++)
    {
        stream << iter.key() << "," << iter.value() << "\n";
    }
    file.flush();
    file.close();
}

void CLaserPath::ReadBeamPosMapCsv()
{
    //QString strPath = CMakePath::make_config_path(m_sName + "_LaserBeamWidth.csv");
    QString strPath = GetFilePath("LaserBeamWidth.csv");

    QFile file(strPath);
    if (!file.open(QIODevice::ReadOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }
    m_mBeamPos.clear();
    QTextStream stream(&file);
    while (!file.atEnd())
    {
        QString sLine = file.readLine();
        if (sLine.isEmpty())
        {
            continue;
        }

        QStringList paramList = sLine.split(",");
        if (paramList.count() < 2)
        {
            continue;
        }
        int iWidth = paramList[0].toInt();
        double dPos = paramList[1].toDouble();

        m_mBeamPos[iWidth] = dPos;
    }
    file.close();
}

bool CLaserPath::GetLineWidthParam(double dWidth, DIndexParam& param)
{
    bool bFixSetting = m_Variants.get_VData(Var_LaserPath_UseFixSetting)->toBool();

    if (bFixSetting && _Sys_Instance_.m_Variants.get_VData(Var_Enable_FixLaserPathAngle)->toBool())
    {
        param.dAngle1 = m_Variants.get_VData(Var_LaserPath_Angle1)->toDouble();
        param.dAngle2 = m_Variants.get_VData(Var_LaserPath_Angle2)->toDouble();
        return true;
    }
    int iDIndex = int(dWidth * 1000);
    for (auto iter = m_vDIndexParam.begin(); iter != m_vDIndexParam.end(); ++iter)
    {
        if (iDIndex == iter->first)
        {
            param = iter->second;

            //TODO:可能需要添加初始值，以适应更新
            double dOffset1 = 0;
            double dOffset2 = 0;
            param.dAngle1 += dOffset1;
            param.dAngle2 += dOffset2;

            return true;
        }
    }

    //没有找到数据
    MQT_THROW_STR(QObject::tr("not find current line width %1 parameter").arg(dWidth));
}

bool CLaserPath::FindPowerPosVector(int iFreq, int iEpulse, double dBeamWidth,
                                    POWERPOSVECTOR& vector)
{
    if (m_iID == LASERPATH_D_NARROW)
    {
        dBeamWidth = 0;
    }
    int iWidth = int(dBeamWidth * 1000);

    CPowerIndex Index = CPowerIndex(iFreq, iEpulse, iWidth);
    int iSize = m_mPowerCali.size();
    for (int i = 0; i < iSize; i++)
    {
        if (m_mPowerCali[i].first == Index)
        {
            vector = m_mPowerCali[i].second;
            return true;
        }
    }
    return false;
}

bool CLaserPath::AddPowerPosVector(int iFreq, int iEpulse, double dBeamWidth, POWERPOSVECTOR& vector)
{
    if (m_iID == LASERPATH_D_NARROW || m_iID == LASERPATH_S_NARROW)
    {
        dBeamWidth = 0;
    }
    int iWidth = int(dBeamWidth * 1000);

    CPowerIndex Index = CPowerIndex(iFreq, iEpulse, iWidth);
    int iSize = m_mPowerCali.size();
    for (int i = 0; i < iSize; i++)
    {
        if (Index == m_mPowerCali[i].first)
        {
            m_mPowerCali[i].second = vector;
            return true;
        }
    }

    QPair<CPowerIndex, POWERPOSVECTOR> ParamPair;
    ParamPair.first = Index;
    ParamPair.second = vector;
    m_mPowerCali.push_back(ParamPair);
    return true;
}


double CLaserPath::PowerToAngle(int iFreq, int iEpulse, double dBeamWidth, double dPower)
{
    if (m_iID == LASERPATH_S_NARROW)
    {
        dBeamWidth = 0;
    }

    if (true == m_Variants.get_VData(Var_LaserPath_UseFixPowerSetting)->toBool()
        && _Sys_Instance_.m_Variants.get_VData(Var_Enable_FixLaserPathAngle)->toBool())
    {
        return m_Variants.get_VData(Var_LaserPath_PowerSet)->toDouble();
    }

    POWERPOSVECTOR Param;
    bool b = FindPowerPosVector(iFreq, iEpulse, dBeamWidth, Param);
    QString beamWidth = _SysExt_Instance.m_mapNameList[m_iID];
    if (dPower < 0)
    {
        MQT_THROW_STR(beamWidth + QObject::trUtf8("Power map err.source power<0"));
    }
    if (!b)
    {
        MQT_THROW_STR(beamWidth + QObject::trUtf8("Power map err."
                      "Freq: %1KHz,Width: %2mm has not cali.")
                      .arg(iFreq).arg(dBeamWidth));
    }
    int iSize = Param.size();
    if (iSize <= 2)
    {
        MQT_THROW_STR(beamWidth + QObject::trUtf8("Power map err."
                      "Freq: %1KHz,Width: %2mm has not cali.")
                      .arg(iFreq).arg(dBeamWidth));
    }

    if (dPower > Param.at(iSize - 1).dPower)
    {
        MQT_THROW_STR(beamWidth + QObject::trUtf8("Power map err."
                      "%1KHz source Power:%2 >Max Power:%3")
                      .arg(iFreq).arg(dPower)
                      .arg(Param.at(iSize - 1).dPower));
    }
    else if (dPower < Param.at(0).dPower)
    {
        MQT_THROW_STR(beamWidth + QObject::trUtf8("Power map err."
                      "%1KHz source Power:%2 <Min Power:%3")
                      .arg(iFreq).arg(dPower)
                      .arg(Param.at(0).dPower));
    }

    //Wide是单调递减，Narrow是单调递增
    //功率必须要是单调递增
    double dNeedPower = dPower;
    for (int i = iSize - 1; i > 0; i--)
    {
        //小值
        double dPower1 = Param.at(i - 1).dPower;
        double dAngle1 = Param.at(i - 1).dIndex;

        //大值
        double dPower2 = Param.at(i).dPower;
        double dAngle2 = Param.at(i).dIndex;

        if (dPower1 <= dPower && dPower2 >= dPower)
        {
            double dOffset = (dAngle2 - dAngle1) / (dPower2 - dPower1) * (dNeedPower - dPower1);
            /*double dPowerMaxAngle =
                m_Variants.get_VData(Var_LaserPath_PowerMaxAngle_ID)->toDouble();*/
            return  dAngle1 + dOffset;
        }
    }
    Q_ASSERT(0);
    return 0;
}


QString CLaserPath::GetFilePath(QString sFileName)
{
    return CMakePath::make_config_path(m_sName + "/" + m_sName + "_" + sFileName);
}

void CLaserPath::WritePowerPosMap()
{
    QString strPath =
        CMakePath::make_config_path(m_sName + "_LaserCaliData.ldf");
    if (m_iID == LASERPATH_D_NARROW)
    {
        strPath = CMakePath::make_config_path("D_NARROW_LaserCaliData.ldf");
    }
    else if (m_iID == LASERPATH_D_WIDE)
    {
        strPath = CMakePath::make_config_path("D_WIDE_LaserCaliData.ldf");
    }
    QFile file(strPath);
    if (!file.open(QIODevice::WriteOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }
    QDataStream stream(&file);
    int iSize = m_mPowerCali.size();
    stream << iSize;
    CALIMAP::iterator ii;
    for (ii = m_mPowerCali.begin(); ii != m_mPowerCali.end(); ii++)
    {
        stream << ii->first.iFreq << ii->first.iEpulse << ii->first.iWidth;
        POWERPOSVECTOR& ParamVector = ii->second;
        int iSizeReal = ParamVector.size();
        stream << iSizeReal;
        for (int i = 0; i < iSizeReal; i++)
        {
            stream << ParamVector[i].dIndex;
            stream << ParamVector[i].dPower;
            stream << ParamVector[i].dPower_RT;
        }
    }
}

void CLaserPath::ReadPowerPosMap()
{
    /*QString strPath=
            CMakePath::make_config_path(m_sName+"_LaserCaliData.ldf");*/
            /*QString strPath =
                CMakePath::make_config_path(m_sName + "_LaserCaliData.ldf");
            if(m_iID == LASERPATH_D_NARROW) {
                strPath = CMakePath::make_config_path("D_NARROW_LaserCaliData.ldf");
            } else if(m_iID == LASERPATH_D_WIDE) {
                strPath = CMakePath::make_config_path("D_WIDE_LaserCaliData.ldf");
            } */

    QString strPath = GetFilePath("LaserCaliData.ldf");

    QFile file(strPath);
    if (!file.open(QIODevice::ReadOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }
    QDataStream stream(&file);
    m_mPowerCali.clear();
    int iSize;
    stream >> iSize;
    for (int j = 0; j < iSize; j++)
    {
        QPair<CPowerIndex, POWERPOSVECTOR> ParamPair;
        stream >> ParamPair.first.iFreq >> ParamPair.first.iEpulse >> ParamPair.first.iWidth;
        int iSizeVector;
        stream >> iSizeVector;

        POWERPOSVECTOR& ParamVector = ParamPair.second;
        ParamVector.resize(iSizeVector);
        /*if(m_gSystem.IsSimulator()) {
            iSizeVector = 45;
            ParamVector.resize(iSizeVector);
            for(int i = 0; i < iSizeVector; i++) {
                ParamVector[i].dIndex = i;
                ParamVector[i].dPower = i * 1.0 / 3;
                ParamVector[i].dPower_RT = i / 13;
            }
            m_mPowerCali.push_back(ParamPair);
            break;
        }*/

        for (int i = 0; i < iSizeVector; i++)
        {
            stream >> ParamVector[i].dIndex;
            stream >> ParamVector[i].dPower;
            stream >> ParamVector[i].dPower_RT;
        }
        m_mPowerCali.push_back(ParamPair);
    }
}

void CLaserPath::WritePowerPosMapCsv()
{
    QString strPath =
        CMakePath::make_config_path(m_sName + "_LaserCaliData.csv");
    if (m_iID == LASERPATH_D_NARROW)
    {
        strPath = CMakePath::make_config_path("D_NARROW_LaserCaliData.csv");
    }
    else if (m_iID == LASERPATH_D_WIDE)
    {
        strPath = CMakePath::make_config_path("D_WIDE_LaserCaliData.csv");
    }
    QFile file(strPath);
    if (!file.open(QIODevice::WriteOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }
    QTextStream stream(&file);
    int iSize = m_mPowerCali.size();
    stream << iSize << "\n";
    CALIMAP::iterator ii;
    for (ii = m_mPowerCali.begin(); ii != m_mPowerCali.end(); ii++)
    {
        stream << "Freq," << ii->first.iFreq << ",Epulse," << ii->first.iEpulse << ",Width," << ii->first.iWidth << "\n";
        POWERPOSVECTOR& ParamVector = ii->second;
        int iSizeReal = ParamVector.size();
        stream << "VectorCount," << iSizeReal << "\n";;
        for (int i = 0; i < iSizeReal; i++)
        {
            stream << ParamVector[i].dIndex << ",";
            stream << ParamVector[i].dPower << ",";
            stream << ParamVector[i].dPower_RT << ",";
            stream << "\n";
        }
    }
}
#ifdef __USE_LASER_BAEM__POWER__
bool CLaserPath::AddBeamPosVector(int iFreq, int iEpulse, double dBeamWidth, BEAMPOSVECTOR& vector)
{
    int iWidth = int(dBeamWidth * 1000);

    CPowerIndex Index = CPowerIndex(iFreq, iEpulse, iWidth);
    int iSize = m_mBeamCali.size();
    for (int i = 0; i < iSize; i++)
    {
        if (Index == m_mBeamCali[i].first)
        {
            m_mBeamCali[i].second = vector;
            return true;
        }
    }

    QPair<CPowerIndex, BEAMPOSVECTOR> ParamPair;
    ParamPair.first = Index;
    ParamPair.second = vector;
    m_mBeamCali.push_back(ParamPair);
    return true;
}

bool CLaserPath::FindBeamPosVector(int iFreq, int iEpulse, double dBeamWidth, BEAMPOSVECTOR& vector)
{
    if (m_iID == LASERPATH_D_NARROW)
    {
        dBeamWidth = 0;
    }
    int iWidth = int(dBeamWidth * 1000);

    CPowerIndex Index = CPowerIndex(iFreq, iEpulse, iWidth);
    int iSize = m_mBeamCali.size();
    for (int i = 0; i < iSize; i++)
    {
        if (m_mBeamCali[i].first == Index)
        {
            vector = m_mBeamCali[i].second;
            return true;
        }
    }
    return false;
}

void CLaserPath::AddToBeamWidePower(int iFreq, int iEpulse, double dBeamWidth, double dPower)
{
    DBeamWideScale param;
    param.dWide = dBeamWidth;
    param.dPower = dPower;
    param.iFreq = iFreq;
    param.iEpulse = iEpulse;
    if (m_vScaleParam.size())
    {
        param.dScale = dPower / m_vScaleParam[0].dPower;
    }
    else
    {
        param.dScale = 1;
    }
    m_vScaleParam.push_back(param);
}

double CLaserPath::CalcuPowerToAngle(int iFreq, int iEpulse, double dBeamWidth, double dPower)
{
#ifndef __USE_LASER_BAEM__POWER__
    return dBeamWidth;
#endif
    if (m_iID != LASERPATH_D_WIDE
        || m_vScaleParam.size() < 1)
    {
        return 1;
    }

    for (PowerParamIndex& param : m_vPowerPos)
    {
        if (abs(param.dPower - dPower) < 0.001)
        {
            return param.dIndex;
        }
    }

    auto it_min = std::min_element(m_vScaleParam.begin(), m_vScaleParam.end(),
                                   [dBeamWidth](const DBeamWideScale& a, const DBeamWideScale& b)
    {
        return std::abs(a.dWide - dBeamWidth) < std::abs(b.dWide - dBeamWidth);
    });

    auto it_max = std::max_element(m_vScaleParam.begin(), m_vScaleParam.end(),
                                   [dBeamWidth](const DBeamWideScale& a, const DBeamWideScale& b)
    {
        return std::abs(a.dWide - dBeamWidth) > std::abs(b.dWide - dBeamWidth);
    });

    if (it_min != m_vScaleParam.end()
        && it_max != m_vScaleParam.end())
    {
        if (it_min->dWide <= dBeamWidth && it_max->dWide >= dBeamWidth)
        {
            double dOffset = (it_max->dScale - it_min->dScale) / (it_max->dWide - it_min->dWide) * (dBeamWidth - it_min->dWide);
            dPower = dPower * (it_max->dScale + dOffset);
        }
    }

    return PowerToAngle(iFreq, iEpulse, dBeamWidth, dPower);
}

bool CLaserPath::ReadBeamWideScaleCsv()
{
    if (m_iID != LASERPATH_D_WIDE)
    {
        return true;
    }

    QString strPath = CMakePath::make_config_path(m_sName + "_LaserBeamWidthScale.csv");

    QFile file(strPath);
    if (!file.open(QIODevice::ReadOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }
    m_vScaleParam.clear();
    QTextStream stream(&file);
    while (!file.atEnd())
    {
        QString sLine = file.readLine();
        if (sLine.isEmpty())
        {
            continue;
        }

        QStringList paramList = sLine.split(",");
        if (paramList.count() < 3)
        {
            continue;
        }

        DBeamWideScale pairAngle;
        pairAngle.dWide = paramList[0].toDouble();
        pairAngle.dScale = paramList[1].toDouble();
        pairAngle.dPower = paramList[2].toDouble();

        m_vScaleParam.push_back(pairAngle);
    }

    file.close();

    return true;
}

void CLaserPath::WriteBeamWideScaleCsv()
{
    if (m_iID != LASERPATH_D_WIDE)
    {
        return;
    }

    QString strPath = CMakePath::make_config_path(m_sName + "_LaserBeamWidthScale.csv");

    QFile file(strPath);
    if (!file.open(QIODevice::WriteOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }
    QTextStream stream(&file);

    for (auto iter : m_vScaleParam)
    {
        stream << iter.dWide << "," << iter.dScale
            << "," << iter.dPower << "\n";
    }
    file.flush();
    file.close();
}

void CLaserPath::WriteBeamScaleMap()
{
    QString strPath =
        CMakePath::make_config_path(m_sName + "_LaserCaliBeamScaleData.ldf");
    if (m_iID == LASERPATH_D_NARROW)
    {
        strPath = CMakePath::make_config_path("D_NARROW_LaserCaliBeamScaleData.ldf");
    }
    else if (m_iID == LASERPATH_D_WIDE)
    {
        strPath = CMakePath::make_config_path("D_WIDE_LaserCaliBeamScaleData.ldf");
    }
    QFile file(strPath);
    if (!file.open(QIODevice::WriteOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }
    QDataStream stream(&file);
    int iSize = m_mBeamCali.size();
    stream << iSize;
    CALIBEAMMAP::iterator ii;
    for (ii = m_mBeamCali.begin(); ii != m_mBeamCali.end(); ii++)
    {
        stream << ii->first.iFreq << ii->first.iEpulse << ii->first.iWidth;
        BEAMPOSVECTOR& ParamVector = ii->second;
        int iSizeReal = ParamVector.size();
        stream << iSizeReal;
        for (int i = 0; i < iSizeReal; i++)
        {
            stream << ParamVector[i].dScale;
            stream << ParamVector[i].dPower;
            stream << ParamVector[i].dWide;
            stream << ParamVector[i].iFreq;
            stream << ParamVector[i].iEpulse;
        }
    }
}

void CLaserPath::ReadBeamScaleMap()
{
    /*QString strPath=
    CMakePath::make_config_path(m_sName+"_LaserCaliData.ldf");*/
    QString strPath =
        CMakePath::make_config_path(m_sName + "_LaserCaliBeamScaleData.ldf");
    if (m_iID == LASERPATH_D_NARROW)
    {
        strPath = CMakePath::make_config_path("D_NARROW_LaserCaliBeamScaleData.ldf");
    }
    else if (m_iID == LASERPATH_D_WIDE)
    {
        strPath = CMakePath::make_config_path("D_WIDE_LaserCaliBeamScaleData.ldf");
    }
    QFile file(strPath);
    if (!file.open(QIODevice::ReadOnly))
    {
        MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
                      .arg(strPath));
    }
    QDataStream stream(&file);
    m_mBeamCali.clear();
    int iSize;
    stream >> iSize;
    for (int j = 0; j < iSize; j++)
    {
        QPair<CPowerIndex, BEAMPOSVECTOR> ParamPair;
        stream >> ParamPair.first.iFreq >> ParamPair.first.iEpulse >> ParamPair.first.iWidth;
        int iSizeVector;
        stream >> iSizeVector;

        BEAMPOSVECTOR& ParamVector = ParamPair.second;
        ParamVector.resize(iSizeVector);

        for (int i = 0; i < iSizeVector; i++)
        {
            stream >> ParamVector[i].dScale;
            stream >> ParamVector[i].dPower;
            stream >> ParamVector[i].dWide;
            stream >> ParamVector[i].iFreq;
            stream >> ParamVector[i].iEpulse;
        }
        m_mBeamCali.push_back(ParamPair);
    }
}
#endif