#include "CivBuilder.h"
#include "CivTypes.h"

CivInpBuilder::CivInpBuilder()
	:mDbConn(nullptr)
{

}

CivInpBuilder::CivInpBuilder(CivDbConn* dbConn)
	:mDbConn(dbConn)
{

}

CivInpBuilder::~CivInpBuilder()
{
	delete mDbConn;
}

void CivInpBuilder::registDb(CivDbConn* dbConn)
{
	if (mDbConn != nullptr)
	{
		delete mDbConn;
		mDbConn = nullptr;
	}
	mDbConn = dbConn;
}

bool CivInpBuilder::exportInp(char* fileName)
{
    //1 ,获取管网组件
    if (!mDbConn)
        return false;

    if (!mDbConn->open())
        return false;

    bool pattern = mDbConn->createTable(PATTERNTABLE, "public", CivTableTemp::PATTERN_TABLE);
    bool  cii = mDbConn->createTable(OPTIONTTABLE, "public", CivTableTemp::PARAMETER_TABLE);

    // 获取表格
    Tables tables = mDbConn->getTables("进贤","public");

    //2,解析管网组件
    // 解析管网组件顺序: 管线放最后
    CivInp civInp(CivInp::HOURS);

    int total = tables.size();
    for (int i = 0; i < total; i++)
    {
        std::string table = tables[i];
        if (PIPELINE == table)
            continue;

        builder(table, civInp);
    }
    builder(PIPELINE, civInp);


    // 设置曲线
    // Componets curves = mDbConn->getComponets(CURVETABLE);

    // 初始化参数
    Options options;
    options.units = Options::UNITS::LPS;
    options.TRIALS = "40";
    options.ACCURACY = "0.001 ";
    options.EMITTEREXPONENT = "0.5";
    options.SpecificGravity = "0.998";
    options.headLoss = Options::HEADLOSS::HW;
    options.TOLERANCE = "0.0166666666666667 ";
    options.quality = Options::QUALITY::AGE;

    std::map<std::string, std::string> optMap;
    optMap.insert(std::pair<std::string, std::string>("DAMPLIMIT", "0"));
    optMap.insert(std::pair<std::string, std::string>("CHECKFREQ", "2"));
    optMap.insert(std::pair<std::string, std::string>("MAXCHECK", "10"));

    civInp.setOption(options, optMap);

    // 设置
    civInp.setDuration(24);
    civInp.setTimestep("PATTERN", 1);
    civInp.setTimestep("HYDRAULIC", 1);
    civInp.setTimestep("QUALITY", 1);

    civInp.setTimeStart("REPORT", 1);

    civInp.writeToFile(fileName);
    return true;
}

void CivInpBuilder::builder(StrQuote table, CivInp& inp)
{
    // 根据组建类型解析字段
    if (PIPELINE == table)
    {
        // 管线
        //;ID  Node1   Node2   Length   Diameter  	Roughness  MinorLoss  Status
        // 必备参数
        Componets comps = mDbConn->getComponets(table);
        PipeFields pipes;
        Civitems items;
        int total = comps.size();
        for (int i = 0; i < total; i++)
        {
            Componet comp = comps[i];

            // 过滤掉与阀门和水泵连接的管线
            Str number = comp.find("id")->second;
            FiledFilter filter = mDbConn->getFilter();
            auto iter = filter.find(PIPELINE);
            if (iter != filter.end())
            {
                auto lineFilter = iter->second;
                if (lineFilter.count(number) > 0)
                    continue;
            }

            Str id = comp.find(pipes.ID)->second;
            Str startNode = comp.find(pipes.Node1)->second;
            Str endNode = comp.find(pipes.Node2)->second;
            Str length = comp.find(pipes.Length)->second;
            Str diameter = comp.find(pipes.Diameter)->second;
            Str roughness = comp.find(pipes.Roughness)->second;
            Str minorLoss = comp.find(pipes.MinorLoss)->second;
            Str status = comp.find(pipes.Status)->second;

            // 注意顺序
            CivItem civItem;
            if (id == "" || id.empty())
                id = "GD" + comp.find("id")->second;
            civItem.push_back(id);
            civItem.push_back(startNode);
            civItem.push_back(endNode);
            civItem.push_back(length);
            civItem.push_back(diameter);
            civItem.push_back(roughness);
            civItem.push_back(minorLoss);
            civItem.push_back(status);
            items.push_back(civItem);
        }
        inp.writeComponet(items, _PIPES);

    }
    else if (PIPENODE == table)
    {
        Componets comps = mDbConn->getComponets(table);
        // 节点参数
        // ;ID              	Elev        	Demand      	Pattern
         // 坐标  
        //;Node            	X-Coord         	Y-Coord
        JunctionsFields jontionFields;
        Civitems jounItems;
        Civitems nodeCoordItems;
        Civitems patternItems;

        int total = comps.size();
        std::set<Str> patterNams;
        for (int i = 0; i < total; i++)
        {
            Componet comp = comps[i];
            Str id = comp.find(jontionFields.ID)->second;
            Str elevation = comp.find(jontionFields.Elev)->second;
            Str demand = comp.find(jontionFields.Demand)->second;
            Str pattern = comp.find(jontionFields.Pattern)->second;
            Str x_coord = comp.find(jontionFields.X_Coord)->second;
            Str y_coord = comp.find(jontionFields.Y_Coord)->second;

            // 注意顺序
            //1, 节点
            CivItem civItem;
            civItem.push_back(id);
            civItem.push_back(elevation);
            civItem.push_back(demand);
            civItem.push_back(pattern);

            jounItems.push_back(civItem);

            // 2, 节点坐标
            CivItem nodeCoordItem;
            nodeCoordItem.push_back(id);
            nodeCoordItem.push_back(x_coord);
            nodeCoordItem.push_back(y_coord);

            nodeCoordItems.push_back(nodeCoordItem);
            if (!pattern.empty())
            {
                patterNams.insert(pattern);
            }

        }

        Componets patterns = mDbConn->getComponets(PATTERNTABLE);
        PatternFields fileds;
        size_t patternSize = patterns.size();
        for (int i = 0; i < patternSize; i++)
        {
            Componet pattern = patterns[i];
            Str paternName = pattern.find(fileds.Name)->second;
            Str paternValue = pattern.find(fileds.Value)->second;

            CivItem item;
            item.push_back(paternName);
            item.push_back(paternValue);

            patternItems.push_back(item);
        }
        inp.writeComponet(jounItems, _JUNCTIONS);
        inp.writeComponet(nodeCoordItems, _COORDS);
        inp.writeComponet(patternItems, _PATTERNS);
    }
    else if (RESIVOIR == table) // 水源
    {
        Componets comps = mDbConn->getComponets(table);
        //;ID              	Head        	Pattern
        Civitems coordItems;
        Civitems resirvoirItems;

        ResivoirFields fields;
        int total = comps.size();
        for (int i = 0; i < total; i++)
        {
            Componet comp = comps[i];
            Str id = comp.find(fields.ID)->second;
            Str elevation = comp.find(fields.Elev)->second;
            Str flow = comp.find(fields.Flow)->second;
            Str head = comp.find(fields.Head)->second;
            Str pattern = comp.find(fields.Pattern)->second;
            Str x_coord = comp.find(fields.X_Coord)->second;
            Str y_coord = comp.find(fields.Y_Coord)->second;

            // 注意顺序
            //1, coord
            CivItem civItem;
            civItem.push_back(id);
            civItem.push_back(head);
            civItem.push_back(pattern);

            resirvoirItems.push_back(civItem);

            // 2, 节点坐标
            CivItem nodeCoordItem;
            nodeCoordItem.push_back(id);
            nodeCoordItem.push_back(x_coord);
            nodeCoordItem.push_back(y_coord);

            coordItems.push_back(nodeCoordItem);
        }

        inp.writeComponet(coordItems, _COORDS);
        inp.writeComponet(resirvoirItems, _RESERVOIRS);

    }
    else if (PUMP == table) // 水泵
    {
        //;ID              	Node1           	Node2           	Parameters
        Componets comps = mDbConn->getLikelyPipes(table);
        PumpFields fields;

        Civitems pumpItems;
        int total = comps.size();
        for (int i = 0; i < total; i++)
        {
            Componet comp = comps[i];
            Str id = comp.find(fields.ID)->second;
            Str node1 = comp.find(fields.node1)->second;
            Str node2 = comp.find(fields.node2)->second;

            std::vector<Str> vec;
            Str head = comp.find(fields.head)->second;
            if (!head.empty())
                vec.push_back("HEAD " + head);

            Str power = comp.find(fields.power)->second;
            if (!power.empty())
                vec.push_back("POWER " + power);

            Str pattern = comp.find(fields.pattern)->second;
            if (!pattern.empty())
                vec.push_back("PATTERN " + pattern);

            Str speed = comp.find(fields.speed)->second;
            if (!speed.empty())
                vec.push_back("SPEED " + speed);

            // 水池数据
            CivItem tankNode;
            tankNode.push_back(id);
            tankNode.push_back(node1);
            tankNode.push_back(node2);

            // 构建参数
            char param[128] = " ";
            int total = vec.size();
            for (int i = 0; i < total; i++)
            {
                strcat_s(param, vec[i].c_str());
            }
            tankNode.push_back(param);
            pumpItems.push_back(tankNode);
        }
        inp.writeComponet(pumpItems, _PUMPS);
    }
    else if (TANK == table) // 水池
    {
        Componets comps = mDbConn->getComponets(table);
        // ; ID              	Elevation   	InitLevel   	MinLevel    	MaxLevel    	Diameter    	MinVol      	VolCurve
        TanksFields tkfFileds;
        Civitems nodeCoordItems;
        Civitems tankItems;
        int total = comps.size();
        for (int i = 0; i < total; i++)
        {
            Componet comp = comps[i];
            Str id = comp.find(tkfFileds.ID)->second;
            Str elevation = comp.find(tkfFileds.Elev)->second;
            Str initLevel = comp.find(tkfFileds.InitLevel)->second;
            Str minLevel = comp.find(tkfFileds.MinLevel)->second;
            Str maxLevel = comp.find(tkfFileds.MaxLevel)->second;
            Str diametor = comp.find(tkfFileds.Diameter)->second;

            Str minVol = comp.find(tkfFileds.MinVol)->second;

            Str x_coord = comp.find(tkfFileds.X_Coord)->second;
            Str y_coord = comp.find(tkfFileds.Y_Coord)->second;

            // 水池数据
            CivItem tankNode;
            tankNode.push_back(id);
            tankNode.push_back(elevation);
            tankNode.push_back(initLevel);
            tankNode.push_back(minLevel);
            tankNode.push_back(maxLevel);
            tankNode.push_back(diametor);
            tankNode.push_back(minVol);

            tankItems.push_back(tankNode);

            // 2, 节点坐标
            CivItem nodeCoordItem;
            nodeCoordItem.push_back(id);
            nodeCoordItem.push_back(x_coord);
            nodeCoordItem.push_back(y_coord);

            nodeCoordItems.push_back(nodeCoordItem);
        }
        inp.writeComponet(nodeCoordItems, _COORDS);
        inp.writeComponet(tankItems, _TANKS);
    }
    else
    {
        // 阀门
        //;ID              	Node1           	Node2           	Diameter    	Type	Setting     	MinorLoss  
        Componets comps = mDbConn->getLikelyPipes(table);
        ValvesFields fields;

        Civitems vavleItems;
        int total = comps.size();
        for (int i = 0; i < total; i++)
        {
            Componet comp = comps[i];
            Str id = comp.find(fields.ID)->second;
            Str node1 = comp.find(fields.node1)->second;
            Str node2 = comp.find(fields.node2)->second;
            Str diametor = comp.find(fields.Diameter)->second;
            Str label = comp.find(fields.type)->second;
            Str typeSeting = comp.find(fields.setting)->second;
            Str minorLoss = comp.find(fields.minorLoss)->second;

            // 阀门数据
            CivItem vavleNode;
            vavleNode.push_back(id);
            vavleNode.push_back(node1);
            vavleNode.push_back(node2);
            vavleNode.push_back(diametor);
            vavleNode.push_back(label);
            vavleNode.push_back(typeSeting);
            vavleNode.push_back(minorLoss);

            vavleItems.push_back(vavleNode);
        }
        inp.writeComponet(vavleItems, _VALVES);
    }
}

void CivInpBuilder::buildNode()
{
    mDbConn->getComponets(PIPENODE);
}

void CivInpBuilder::buildPipe()
{

}

void CivInpBuilder::buildTank()
{

}

void CivInpBuilder::buildVavle()
{

}

void CivInpBuilder::buildPump()
{

}

void CivInpBuilder::buildReservoir()
{

}

void CivInpBuilder::buildEmitter()
{

}

CivNewInp* CivInpBuilder::getNewInp()
{

}


void CivInpBuilder::buildPatterns()
{

}

void CivInpBuilder::buildParamter()
{

}

void CivInpBuilder::buildCoordnates()
{

}

void CivInpBuilder::buildVertices()
{

}

void CivInpBuilder::buildLabels()
{

}

void CivInpBuilder::buildTags()
{

}

void CivInpBuilder::buildBackDrop()
{

}

void CivInpBuilder::buildQuality()
{

}

void CivInpBuilder::buildSources()
{

}

void CivInpBuilder::buildMixing()
{

}

void CivInpBuilder::buildCurves()
{

}

void CivInpBuilder::buildStatus()
{

}

void CivInpBuilder::buildControls()
{

}

void CivInpBuilder::buildRules()
{

}

void CivInpBuilder::buildDemands()
{

}