#include "CivSchedulingCompute.h"
#include "CivCommonUtils.h"
#include "epanet2.h"
#include "types.h"
#include "CivSysLog.h"

CivSchedulingCompute::CivSchedulingCompute(SchdulingType schedulingType)
    :mChdulingType(schedulingType)
{
    mRptFile = "test.rpt";
    mBinFile =  "test.bin";
    mInpFile =  "test.inp";
}

bool CivSchedulingCompute::openFile(const string& inpFILE)
{
    char inpFile[256];
    strcpy_s(inpFile, mInpFile.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;
    }

    return true;
}

bool CivSchedulingCompute::saveInpFile(char* inpFile)
{
    int code = ENsaveinpfile(inpFile);
    if (code > 0)
        return false;
    return true;
}

bool CivSchedulingCompute::calculate()
{
    short hydCode = 1;
    long  t(0), tstep(0);
    int   iTime(0);

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


    float dHStep;
    ENGetVal(4, &dHStep);
  
    int nLinkCount;
    ENgetcount(EN_LINKCOUNT, &nLinkCount);
    for (int i = 1; i <= nLinkCount; i++)
    {
        // 获取管段类型
        int linkType;
        ENgetlinktype(i, &linkType);

        switch (linkType)
        {
        case EN_PUMP:
        {
            char id[128] = "";
            ENgetlinkid(i, id);

            map<string, float>::iterator iter = mPumpSpeed.find(id);
            if (iter != mPumpSpeed.end())
            {
                // 更新水泵的转速
                ENsetlinkvalue(i, EN_STATUS, iter->second);
            }
        }
        break;
        case EN_PIPE:
        case EN_PBV:
        default:
            break;
        }
    }
    do
    {
        if (ENrunH(&t) > 100)	// errcode > 100 是错误
        {
            ENclose();
            return false;
        }

        ENnextH(&tstep);

        // 保存
        saveResult(iTime);

        // 水泵能量
        getPumpEnergy(iTime);

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

    return true;
}

void CivSchedulingCompute::close()
{
    ENcloseH();
    ENclose();
}

void CivSchedulingCompute::updatePumpSpeed(const map<string, float>& pumpSpeed)
{
    mPumpSpeed.clear();
    mPumpSpeed = pumpSpeed;
}

void CivSchedulingCompute::getMonitorsValue(int time, map<string, double>& monitorMap)
{
    if (time<0 || time> mMonitorsValue.size() - 1)
        return;

    monitorMap = mMonitorsValue[time];
}

void CivSchedulingCompute::setMonitors(const vector<string>& monitor)
{
    mMonitors = monitor;
}

void CivSchedulingCompute::saveResult(int time)
{
    // 计算节点
    int nNodeCount;
    ENgetcount(EN_NODECOUNT, &nNodeCount);
   
    map<string, double> pressureMap;

    mMonitorsValue.push_back(pressureMap);

    for (int i = 1; i <= nNodeCount; i++)
    {
        char szNo[256];
        ENgetnodeid(i, szNo);// 编号       

        // 判断是不是监测点
        auto iter = std::find(mMonitors.begin(), mMonitors.end(), szNo);
        if (iter != mMonitors.end())
        {
            float pressure;
            ENgetnodevalue(i, EN_PRESSURE, &pressure); // 压力 

            mMonitorsValue[time].insert(pair<string, double>(szNo, pressure));
        }    
    }
}

void CivSchedulingCompute::getPumpEnergy(int time)
{
    int nLinkCount;
    ENgetcount(EN_LINKCOUNT, &nLinkCount);
    map<string, float> energyMap;
    mPumpEnergy.push_back(energyMap);

    for (int i = 0; i < nLinkCount; i++)
    {
        // 获取管段类型
        int linkType;
        ENgetlinktype(i, &linkType);
        if (EN_PUMP != linkType)
            continue;

        char szNo[256];
        ENgetlinkid(i, szNo);// 编号     

        float energy;
        ENgetlinkvalue(i, EN_ENERGY, &energy);

        // 存储每个时刻的消耗的能量
        mPumpEnergy[time].insert(pair<string,float>(szNo, energy));
    }
}

float CivSchedulingCompute::totalEnergy(int index)
{
    if (index<0 || index > mPumpEnergy.size()-1)
        return 0;

    float totalEnergy = 0;
    map<string, float> energyMap = mPumpEnergy[index];
    map<string, float>::const_iterator const_iter = energyMap.cbegin();
    for (; const_iter != energyMap.cend(); const_iter++)
    {
        totalEnergy += const_iter->second;
    }

    return totalEnergy;
}

void CivSchedulingCompute::clearLastVals()
{
    mPumpEnergy.clear();
    mMonitorsValue.clear();
}

void CivSchedulingCompute::updatePBVSettings(const string& sn, double pressure)
{

}