#include "TransChkDateEngine.h"
#include "myutils.h"
#include <regex>

using namespace ai_matrix;

namespace
{
    //按照x坐标排列
    bool CompareX(const SingleData &v1, const SingleData &v2)
    {
        return (v1.fLTX < v2.fLTX);
    }
}

TransChkDateEngine::TransChkDateEngine() {}

TransChkDateEngine::~TransChkDateEngine() {}

APP_ERROR TransChkDateEngine::Init()
{
    bUseEngine_ = MyUtils::getins()->ChkIsHaveTarget("CHKDATE");
    if (!bUseEngine_)
    {
        LogWarn << "engineId_:" << engineId_ << " not use engine";
        return APP_ERR_OK;
    }
    strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
    modelConfig_ = MyYaml::GetIns()->GetModelConfig("ChkDateStepTwoEngine");

    //读取模型参数信息文件
    Json::Value jvModelInfo;
    if (!MyUtils::getins()->ReadJsonInfo(jvModelInfo, modelConfig_.strModelInfoPath))
    {
        LogError << "ModelInfoPath:" << modelConfig_.strModelInfoPath << " doesn't exist or read failed!";
        return APP_ERR_COMM_NO_EXIST;
    }
    for (int i = 0; i < jvModelInfo["class"].size(); i++)
    {
        vecClassNames_.push_back(jvModelInfo["class"][i].asString());
    }

    LogInfo << "TransChkDateEngine Init ok";
    return APP_ERR_OK;
}

APP_ERROR TransChkDateEngine::DeInit()
{
    if (!bUseEngine_)
    {
        LogWarn << "engineId_:" << engineId_ << " not use engine";
        return APP_ERR_OK;
    }
    LogInfo << "TransChkDateEngine DeInit ok";
    return APP_ERR_OK;
}

/**
* push数据到队列，队列满时则休眠一段时间再push
* inParam : const std::string strPort                           push的端口
          : const std::shared_ptr<ProcessData> &pProcessData    push的数据
* outParam: N/A
* return  : N/A
*/
void TransChkDateEngine::PushData(const std::string &strPort, const std::shared_ptr<ProcessData> &pProcessData)
{
    while (true)
    {
        int iRet = outputQueMap_[strPort]->push(std::static_pointer_cast<void>(pProcessData));
        if (iRet != 0)
        {
            LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " push fail iRet:" << iRet;
            if (iRet == 2)
            {
                usleep(10000); // 10ms
                continue;
            }
        }
        break;
    }
}

/**
* 定检期框内容转换
* inParam : std::map<int, std::vector<SingleData>> &mapLine
* outParam: TransSubData &transSubData
* return  : N/A
*/
void TransChkDateEngine::TransChkDate(TransSubData &transSubData, std::map<int, std::vector<SingleData>> &mapLine)
{
    //定检期1 (段修)
    if (mapLine.find(0) != mapLine.end())
    {
        TransInfo ChkDate1Info;
        ChkDate1Info.iLine = 0;
        std::string strTemp = "";
        for (auto j = 0; j < mapLine.at(0).size(); j++)
        {
            //过滤非数字
            std::string strOne = vecClassNames_.at(mapLine.at(0).at(j).iClassId);
            if (strOne[0] < '0' || strOne[0] > '9')
            {
                LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in chkdate1";
                continue;
            }
            strTemp += strOne;
            ChkDate1Info.vecValue.emplace_back(strOne);
            ChkDate1Info.vecScore.emplace_back(mapLine.at(0).at(j).fScore);
            transSubData.fScoreSum += mapLine.at(0).at(j).fScore;
        }

        //本次先不做结果校验，IsChkFlag默认为true
        ChkDate1Info.IsChkFlag = true;
        transSubData.vecTransInfo.emplace_back(ChkDate1Info);
    }

    //定检期2 (厂修)
    if (mapLine.find(1) != mapLine.end())
    {
        TransInfo ChkDate2Info;
        ChkDate2Info.iLine = 1;
        std::string strTemp = "";
        for (auto j = 0; j < mapLine.at(1).size(); j++)
        {
            //过滤非数字
            std::string strOne = vecClassNames_.at(mapLine.at(1).at(j).iClassId);
            if (strOne[0] < '0' || strOne[0] > '9')
            {
                LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in chkdate2";
                continue;
            }
            strTemp += strOne;
            ChkDate2Info.vecValue.emplace_back(strOne);
            ChkDate2Info.vecScore.emplace_back(mapLine.at(1).at(j).fScore);
            transSubData.fScoreSum += mapLine.at(1).at(j).fScore;
        }

        //本次先不做结果校验，IsChkFlag默认为true
        ChkDate2Info.IsChkFlag = true;
        transSubData.vecTransInfo.emplace_back(ChkDate2Info);
    }
}

APP_ERROR TransChkDateEngine::Process()
{
    if (!bUseEngine_)
    {
        LogWarn << "engineId_:" << engineId_ << " not use engine";
        return APP_ERR_OK;
    }

    int iRet = APP_ERR_OK;
    while (!isStop_)
    {
        std::shared_ptr<void> pVoidData0 = nullptr;
        inputQueMap_[strPort0_]->pop(pVoidData0);
        if (nullptr == pVoidData0)
        {
            usleep(1000); //1ms
            continue;
        }

        std::shared_ptr<ProcessData> pProcessData = std::static_pointer_cast<ProcessData>(pVoidData0);
        //第2步后处理结果
        std::shared_ptr<PostData> pPostData = std::static_pointer_cast<PostData>(pProcessData->pVoidData);
        
        //组织输出数据
        std::shared_ptr<TransData> pTransData = std::make_shared<TransData>();
        for (size_t i = 0; i < pPostData->vecPostSubData.size(); i++)
        {
            PostSubData postSubData = pPostData->vecPostSubData[i];

            //按字段代号分类
            std::map<int, std::vector<SingleData>> mapLine;
            for (size_t j = 0; j < postSubData.vecSingleData.size(); j++)
            {
                mapLine[postSubData.vecSingleData.at(j).iLine].push_back(postSubData.vecSingleData.at(j));
            }

            //每一行按x坐标排序
            for (auto it = mapLine.begin(); it != mapLine.end(); it++)
            {
                std::sort(it->second.begin(), it->second.end(), CompareX);

                std::string strTemp = "";
                for (auto j = 0; j < it->second.size(); j++)
                {
                    strTemp += vecClassNames_.at(it->second.at(j).iClassId);
                }
                LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " line:" << it->first << "," << strTemp;
            }

            //非定检期大类不处理
            if (postSubData.iBigClassId != 7)
            {
                continue;
            }

            TransSubData transSubData;
            transSubData.iBigClassId = postSubData.iBigClassId;
            transSubData.iCarXH = postSubData.iCarXH;
            transSubData.step1Location = postSubData.step1Location;
            TransChkDate(transSubData, mapLine);

            pTransData->vecTransSubData.emplace_back(transSubData);
        }
        
        pProcessData->pVoidData = std::static_pointer_cast<void>(pTransData);

        //push端口1，定检期选优处理
        PushData(strPort0_, pProcessData);
    }

    return APP_ERR_OK;
}
