#include "CivDynamicCompute.h"

#include "epanet2.h"
#include "types.h"
#include "CivSysLog.h"
#include "StringUtils.h"
#include<map>
#include<string>
#include <regex>

CivDynamicCompute::CivDynamicCompute()
{
    mRptFile = "test.rpt";
    mBinFile = "test.bin";
}

bool CivDynamicCompute::openFile(ConstStringRef fileName)
{
    char inpFile[256];
    strcpy_s(inpFile, fileName.c_str());

    char rptFile[128];
    strcpy_s(rptFile, mRptFile.c_str());

    char binFile[128];
    strcpy_s(binFile, mBinFile.c_str());

    CivSysLog::getInstance()->info("打开inp文件", "CivHydrCompute", __FUNCTION__);

    mErrcode = ENopen(inpFile, rptFile, binFile);
    if (mErrcode > 0)
    {
        CivSysLog::getInstance()->error("ENopen 失败", "CivHydrCompute", __FUNCTION__);
        ENclose();
        return false;
    }

    if (ENopenH() > 0)
    {
        CivSysLog::getInstance()->error("ENopenH 失败", "CivHydrCompute", __FUNCTION__);
        ENclose();
        return false;
    }
    // 将所有节点水质清零
    resetQuality();

    return true;
}

bool CivDynamicCompute::beginCompute()
{
	return true;
}

void CivDynamicCompute::endCompute()
{
    ENcloseH();
    ENclose();
}

void CivDynamicCompute::updatePumpSpeed(ConstStringRef pcode, float speeds)
{

}

bool CivDynamicCompute::compute(int startTime, int endTime)
{
    short hydCode = 1;
    long  t(0), tstep(0);
    int   iTime(0);
    int  errcode = 0;

    if (ENinitH(EN_SAVE) > 0)
    {
        CivSysLog::getInstance()->error("ENinitH 失败", "CivHydrCompute", __FUNCTION__);
        ENclose();
        return false;
    }
    float dHStep;
    ENGetVal(4, &dHStep);

    do
    {
        if (ENrunH(&t) > 100)	// errcode > 100 是错误
        {
            ENcloseH();
            ENclose();
            return false;
        }

        ENnextH(&tstep);
        iTime++;
    } while (tstep > 0);

    ENcloseH();

    // 进行水质分析
    ENopenQ();
    ENinitQ(1);

    t = 0;
    tstep = 0;
    iTime = 0;
    do
    {
        errcode = ENrunQ(&t);	// errcode > 100 是错误
        if (errcode > 100)
        {
            ENcloseQ();
            ENclose();
            return false;
        }
        if (iTime == startTime)
        {
            std::map<std::string, float>::iterator iter = mWaterSourcesMap.begin();
            for (; iter != mWaterSourcesMap.end(); iter++)
            {
                addWaterResiChlorine(iter->first, iter->second);
            }
            
        }
        // 满足条件保存
        if (iTime>=startTime && iTime<=endTime)
        {
            saveResult(iTime);
        }
        iTime++;
        
        ENstepQ(&tstep);
    } while (tstep > 0);

    ENcloseQ();
    ENclose();

    return true;
}

bool  CivDynamicCompute::saveResult(int iTime)
{
    // 计算节点
    int nNodeCount;
    ENgetcount(EN_NODECOUNT, &nNodeCount);

    std::map<std::string, float> qualityMap;
    for (int i = 1; i <= nNodeCount; i++)
    {
        char szNo[256];
        ENgetnodeid(i, szNo);// 编号       

        float quality;
        ENgetnodevalue(i, EN_QUALITY, &quality); // 获取水质
        qualityMap.insert(std::pair<std::string, double>(szNo, quality));
        
    }
    std::string ontheHourStr = onTheHour(iTime);
    mSimulQualityMap.insert(std::pair<std::string, std::map<std::string, float>>(ontheHourStr, qualityMap));

    return true;
}

std::string CivDynamicCompute::onTheHour(int iTime)
{
    if (iTime < 0 || iTime>24)
        return "";

    std::string repStr;
    if (iTime < 10)
        repStr = "0" + std::to_string(iTime) + ":00:00";
    else
        repStr = std::to_string(iTime) + ":00:00";

    std::string dateHour = mStartTime;
    std::vector<std::string> strVec;
    StringUtils::split(mStartTime, strVec);
    if (strVec.size() <= 0)
        return mStartTime;

    std::string dateStr = strVec[0];

    repStr = std::to_string(iTime) + ":00:00";
    return dateStr +" "+repStr;
}

void CivDynamicCompute::addWaterResiChlorine(const std::string& pid, float density)
{
    int nLinkCount;
    ENgetcount(EN_NODECOUNT, &nLinkCount);
    for (int i = 1; i <= nLinkCount; i++)
    {
        // 获取节点类型     
        char id[128];
        ENgetnodeid(i, id);

        // 根据id添加余氯量
        if (strcmp(id, pid.c_str()) == 0)
        {
            ENsetnodevalue(i, EN_INITQUAL, density);
        }
    }
}

void CivDynamicCompute::updateQuality(const std::map<std::string, float>& waterSources)
{
    mWaterSourcesMap = waterSources;
}

void CivDynamicCompute::resetQuality()
{
    int nNodeCount;
    ENgetcount(EN_NODECOUNT, &nNodeCount);

    for (int i = 1; i <= nNodeCount; i++)
    {
        ENsetnodevalue(i, EN_INITQUAL, 0); 
    }
}

void CivDynamicCompute::simulResult(std::map<std::string, std::map<std::string, float>>& resultMap) const
{
    resultMap = mSimulQualityMap;
}