#include "CivInpDbHelper.h"
#include "CivTableFields.h"
#include "CivConnection.h"
#include "CivPgDbConnection.h"

#include <algorithm>

CivInpDbHelper::CivInpDbHelper(const std::string& uri)
	:CivInpHelperAbs(uri)
{
	mCondtion = "1=1 ";
	isDelayTime = true;
}

CivInpDbHelper::~CivInpDbHelper()
{
}

bool CivInpDbHelper::getNode(CivNode& node)
{
	JunctionTable nodeTableFields;
	std::vector<std::string> fields;

	fields.push_back(nodeTableFields.sn);
	fields.push_back(nodeTableFields.elev);
	fields.push_back(nodeTableFields.baseDemand);
	fields.push_back(nodeTableFields.demandPattern);

	std::vector<std::map<std::string,std::string>> resultVector;	
	mDbConn->query(PIPENODE, fields, resultVector, mCondtion);

	// 编辑包装结果
	size_t total = resultVector.size();
	for (int i = 0; i < total; i++)
	{
		std::map<std::string, std::string> map = resultVector[i];
		CivNode::NodeTable nodeTable;

		nodeTable.ID = map.find(nodeTableFields.sn)->second;
		nodeTable.Elev = map.find(nodeTableFields.elev)->second;

		std::string patternID = map.find(nodeTableFields.demandPattern)->second;
		std::string demand = map.find(nodeTableFields.baseDemand)->second;

		handleDelayPattern(demand, patternID, nodeTable.Demand, nodeTable.PatternId);
		//// 是否做延时模拟
		//if (isDelayTime)
		//{
		//	nodeTable.Demand = demand;
		//	nodeTable.PatternId = patternID;
		//}
		//else
		//{
		//	auto iter = mPatterns.find(patternID);
		//	if (iter != mPatterns.end())
		//	{
		//		std::vector<std::string> mulitiers = iter->second;
		//		if (mPatternTime > mulitiers.size())
		//			mPatternTime = mulitiers.size() - 1;

		//		if (mPatternTime < 0)
		//			mPatternTime = 0;

		//		std::string mulitier = mulitiers[mPatternTime];

		//		float intMul = std::atof(mulitier.c_str());
		//		float dem = std::atof(demand.c_str());

		//		demand = std::to_string(dem * intMul);
		//		nodeTable.Demand = demand;
		//	}
		//}
		node.addItem(nodeTable);
	}

	// 添加处理的阀门产生的节点
	size_t size = mNodeVec.size();
	for (int i = 0; i < size; i++)
	{
		node.addItem(mNodeVec[i]);
	}
	return true;
}

bool CivInpDbHelper::getPipe(CivPipe& pipes)
{
	PipeTable pipeTable;

	std::vector<std::string> fields;
	fields.push_back(pipeTable.snNo); 
	fields.push_back(pipeTable.startPoint);
	fields.push_back(pipeTable.endPoint); 
	fields.push_back(pipeTable.length); 
	fields.push_back(pipeTable.diameter); 
	fields.push_back(pipeTable.friction); 
	fields.push_back(pipeTable.localLoss);
	fields.push_back(pipeTable.status);
	fields.push_back(pipeTable.code);
	
	std::vector<std::map<std::string, std::string>> resultVector;

	std::string condition = "\"from_layer\" not in ('阀门','水泵' ) and \"to_layer\" not in ('阀门','水泵' )";
	mDbConn->query(PIPELINE, fields, resultVector, condition);

	size_t total = resultVector.size();
    for (int i = 0; i < total; i++)
    {
        CivPipe::PipesTable pipe;

		std::map<std::string, std::string> map = resultVector[i];

		pipe.ID = map.find(pipeTable.snNo)->second;
		pipe.Node1 = map.find(pipeTable.startPoint)->second;
		pipe.Node2 = map.find(pipeTable.endPoint)->second;
		pipe.Length = map.find(pipeTable.length)->second;
		pipe.Diameter = map.find(pipeTable.diameter)->second;
		pipe.Roughness = map.find(pipeTable.friction)->second;
		pipe.MinorLoss = map.find(pipeTable.localLoss)->second;
		pipe.Status = map.find(pipeTable.status)->second;
		pipe.code = map.find(pipeTable.code)->second;
		pipes.addItem(pipe);
    }
	// 构造的管段
	size_t size = mPipesVec.size();
	for (int i = 0; i < size; i++)
	{
		pipes.addItem(mPipesVec[i]);
	}
	return true;
}

bool CivInpDbHelper::getTank(CivTank& tanks)
{
	TankTable tankTable;

	std::vector<std::string> fields;

	fields.push_back(tankTable.sn);
	fields.push_back(tankTable.elev);
	fields.push_back(tankTable.initLevel);
	fields.push_back(tankTable.minLevel);
	fields.push_back(tankTable.maxLevel);
	fields.push_back(tankTable.diametor);
	fields.push_back(tankTable.minVolume);
	fields.push_back(tankTable.volumeCurve);

	std::vector<std::map<std::string, std::string>> resultVector;
	mDbConn->query(TANK, fields, resultVector, mCondtion);

	size_t total = resultVector.size();
	for (int i = 0; i < total; i++)
	{
		CivTank::TankTable tank;
		std::map<std::string, std::string>map = resultVector[i];

		tank.ID = map.find(tankTable.sn)->second;
		tank.Elev = map.find(tankTable.elev)->second;
		tank.InitLevel = map.find(tankTable.initLevel)->second;
		tank.MinLevel = map.find(tankTable.minLevel)->second;
		tank.MaxLevel = map.find(tankTable.maxLevel)->second;
		tank.Diameter = map.find(tankTable.diametor)->second;
		tank.MinVol = map.find(tankTable.minVolume)->second;
		tank.VolCurve = map.find(tankTable.volumeCurve)->second;
		
		tanks.addItem(tank);
	}
	return true;
}

bool CivInpDbHelper::getValve(CivValve& valves)
{
	/*ValveTable vaveTable;
	std::vector<std::string> fields;

	fields.push_back(vaveTable.sn); 
	fields.push_back(vaveTable.startPoint);
	fields.push_back(vaveTable.endPoint);
	fields.push_back(vaveTable.length);
	fields.push_back(vaveTable.type);
	fields.push_back(vaveTable.setting);
	fields.push_back(vaveTable.lossCoeff);

	std::vector<std::map<std::string, std::string>> resultVector;
	mDbConn->query(VALVE, fields, resultVector, mCondtion);

	size_t totals = resultVector.size();
	for (int i = 0; i < totals; i++)
	{
		CivValve::ValveTable vave;
		std::map<std::string, std::string> map = resultVector[i];

		std::string vaType = map.find(vaveTable.type)->second;
		if (vaType == "BV")
			continue;

		vave.ID = map.find(vaveTable.sn)->second;
		vave.Node1 = map.find(vaveTable.startPoint)->second;
		vave.Node2 = map.find(vaveTable.endPoint)->second;
		vave.Diameter = map.find(vaveTable.length)->second;
		vave.Type = map.find(vaveTable.type)->second;
		vave.Setting = map.find(vaveTable.setting)->second;
		vave.MinorLoss = map.find(vaveTable.lossCoeff)->second;

		valves.addItem(vave);
	}*/

	size_t size = mValuvesVec.size();
	for (int i = 0; i < size; i++)
	{
		valves.addItem(mValuvesVec[i]);
	}

	return true;
}

bool CivInpDbHelper::getPumps(CivPumps& pumps)
{
	PumpTable pmTable;
	std::vector<std::string> fields;

	fields.push_back(pmTable.sn);
	fields.push_back(pmTable.startPoint);
	fields.push_back(pmTable.endPoint);
	fields.push_back(pmTable.headCurve);
	fields.push_back(pmTable.power);

	std::vector<std::map<std::string, std::string>> resultVector;
	mDbConn->query(PUMP, fields, resultVector, mCondtion);
	
	size_t totals = resultVector.size();
	for (int i = 0; i < totals; i++)
	{
		CivPumps::PumpTable pump;
		std::map<std::string, std::string> map = resultVector[i];

		pump.ID = map.find(pmTable.sn)->second;
		pump.Node1 = map.find(pmTable.startPoint)->second;
		pump.Node2 = map.find(pmTable.endPoint)->second;
		std::string param;
		
		std::string curve = map.find(pmTable.headCurve)->second;
		if (curve != "")
			param.append("head " + curve);

		std::string power = map.find(pmTable.power)->second;
		if (power != "")
			param.append(" power " + power);
	
		pump.Parameters = param;
		pumps.addItem(pump);
	}
	return true;
}

bool CivInpDbHelper::getReservoirs(CivReservoirs& reservoirs)
{
	ResourcesTable restemTable;

	std::vector<std::string> fields;

	fields.push_back(restemTable.sn);
	fields.push_back(restemTable.totalHead);
	fields.push_back(restemTable.headPattern);

	std::vector<std::map<std::string, std::string>> resultVector;
	mDbConn->query(RESIVOIR, fields, resultVector, mCondtion);

	size_t totals = resultVector.size();
	for (int i = 0; i < totals; i++)
	{
		CivReservoirs::ReservoirsTable resTable;
		std::map<std::string, std::string> map = resultVector[i];

		resTable.ID = map.find(restemTable.sn)->second;
		resTable.Head = map.find(restemTable.totalHead)->second;
		resTable.Pattern = map.find(restemTable.headPattern)->second;

		reservoirs.addItem(resTable);
	}
	return true;
}

bool CivInpDbHelper::getCoordinates(CivCoordinates& coord)
{
	JunctionTable nodeTable;

	std::vector<std::string> fields;

	fields.push_back(nodeTable.sn);
	fields.push_back(nodeTable.xCoord);
	fields.push_back(nodeTable.yCoord);
	fields.push_back(nodeTable.code);

	std::vector<std::map<std::string, std::string>> resultVector;
	mDbConn->query(PIPENODE, fields, resultVector, mCondtion);
	mDbConn->query(TANK, fields, resultVector, mCondtion);
	mDbConn->query(RESIVOIR, fields, resultVector, mCondtion);

	size_t totals = resultVector.size();
	for (int i = 0; i < totals; i++)
	{
		CivCoordinates::CoordTable coordTable;
		std::map<std::string, std::string> map = resultVector[i];

		coordTable.ID = map.find(fields[0])->second;
		coordTable.XCoord = map.find(fields[1])->second;
		coordTable.YCoord = map.find(fields[2])->second;
		coordTable.code = map.find(nodeTable.code)->second;

		coord.addItem(coordTable);
	}
	// 加入阀门处理的节点坐标
	size_t size = mCoords.size();
	for (int i = 0; i < size; i++)
	{
		coord.addItem(mCoords[i]);
	}

	return true;
}

bool CivInpDbHelper::getQuality(CivQuality& quality)
{
	JunctionTable nodeTable;

	std::vector<std::string> fields;

	fields.push_back(nodeTable.sn);
	fields.push_back(nodeTable.initQuality);
	fields.push_back(nodeTable.chlorine);

	std::vector<std::map<std::string, std::string>> resultVector;
	mDbConn->query(PIPENODE, fields, resultVector, mCondtion);
	mDbConn->query(RESIVOIR, fields, resultVector,mCondtion);
	mDbConn->query(TANK, fields, resultVector, mCondtion);

	size_t totals = resultVector.size();
	for (int i = 0; i < totals; i++)
	{
		CivQuality::QualityTable quliTable;

		std::map<std::string, std::string> map = resultVector[i];
		quliTable.ID = map.find(nodeTable.sn)->second;
		switch (mQualityType)
		{
		
		case Chlorine:
			quliTable.InitQuality = map.find(nodeTable.chlorine)->second;
			break;
		case Age:
		default:
			quliTable.InitQuality = map.find(nodeTable.initQuality)->second;
			break;
		}

		quality.addItem(quliTable);
	}

	return true;
}

bool CivInpDbHelper::getStatus(CivStatus& status)
{
	//ValveTable vaTable;

	//std::vector<std::string> fields;
	//fields.push_back(vaTable.sn);
	//fields.push_back(vaTable.fixedState);
	//fields.push_back(vaTable.type);

	//std::vector<std::map<std::string, std::string>> resultVector;

	//mDbConn->query(VALVE, fields, resultVector);

	//size_t total = resultVector.size();
	//for (int i = 0; i < total; i++)
	//{
	//	CivStatus::StatusTable statTable;

	//	auto resMap = resultVector[i];
	//
	//	std::string state = resMap.find(vaTable.fixedState)->second;
	//	std::string type = resMap.find(vaTable.type)->second;

	//	std::transform(state.begin(), state.end(), state.begin(), ::toupper);
	//	if (type == "BV")
	//		continue;

	//	statTable.ID = resMap.find(vaTable.sn)->second;
	//	statTable.Setting = state;

	//	status.addItem(statTable);
	//}
	// 阀门状态值，
	size_t statuSize = mStatusVec.size();
	for (int i = 0; i < statuSize; i++)
	{
		status.addItem(mStatusVec[i]);
	}
	
	return true;
}

void CivInpDbHelper::handlePump()
{
	
}

void CivInpDbHelper::handleValve()
{
		  //阀门的下游管段
		std::string dwPipeSql = "select pipe.\"编号\", ('UP' || pipe.\"起始节点\") as \"起始节点\", pipe.\"终止节点\", pipe.\"管长\", pipe.\"管径\",\
			pipe.\"摩阻系数\" ,pipe.\"局损系数\" from \"管段\" as pipe where pipe.\"from_layer\" = '阀门'";

		if (!mDbConn->execSql(dwPipeSql))
			return;

		std::vector<std::map<std::string, std::string>> upPipes;
		mDbConn->queryResult(upPipes);
	
		size_t total = upPipes.size();
		for (int i = 0; i < total; i++)
		{
			std::map<std::string, std::string> pipe = upPipes[i];

			CivPipe::Table pipeStruct;
			pipeStruct.ID = pipe.find("编号")->second;
			pipeStruct.code = pipe.find("code")->second;
			pipeStruct.Node1 = pipe.find("起始节点")->second;
			pipeStruct.Node2 = pipe.find("终止节点")->second;
			pipeStruct.Length = pipe.find("管长")->second;
			pipeStruct.Diameter = pipe.find("管径")->second;
			pipeStruct.Roughness = pipe.find("摩阻系数")->second;
			pipeStruct.Status = "Open";
			pipeStruct.MinorLoss = pipe.find("局损系数")->second;

			mPipesVec.push_back(pipeStruct);
		}
	
		 // 阀门的上游管段
		std::string upPipeSql = "select pipe.\"编号\", pipe.\"起始节点\", ('DW' || pipe.\"终止节点\") as \"终止节点\", pipe.\"管长\", pipe.\"管径\", \
			pipe.\"摩阻系数\",pipe.\"局损系数\" from \"管段\" as pipe where pipe.\"to_layer\" = '阀门'";

		if (!mDbConn->execSql(upPipeSql))
			return;

		std::vector<std::map<std::string, std::string>> downPipes;
		mDbConn->queryResult(downPipes);

		size_t dtotal = downPipes.size();
		for (int i = 0; i < dtotal; i++)
		{
			std::map<std::string, std::string> pipe = downPipes[i];

			CivPipe::Table pipeStruct;
			pipeStruct.ID = pipe.find("编号")->second;
			pipeStruct.code = pipe.find("code")->second;
			pipeStruct.Node1 = pipe.find("起始节点")->second;
			pipeStruct.Node2 = pipe.find("终止节点")->second;
			pipeStruct.Length = pipe.find("管长")->second;
			pipeStruct.Diameter = pipe.find("管径")->second;
			pipeStruct.Roughness = pipe.find("摩阻系数")->second;
			pipeStruct.Status = "Open";
			pipeStruct.MinorLoss = pipe.find("局损系数")->second;

			mPipesVec.push_back(pipeStruct);
		}

		//-- 阀门信息--
		// 构造阀门起始节点
		std::string vaStartSql = "SELECT \
		'UP' || va.\"本点号\" AS \"本点号\", vnode.\"高程\", vnode.\"基本需水量\", vnode.\"需水量模式\" \
		, (va.\"横坐标\" - 1) AS \"横坐标\", (va.\"纵坐标\" - 1) AS \"纵坐标\", va.\"本点号\" as \"阀门本点号\",\
		va.\"类型\" as \"阀门类型\", ('UP' || va.\"本点号\") as \"阀门起始节点\", \
		va.\"直径\" as \"阀门直径\",va.\"固定状态\" as \"阀门状态\",va.\"设置\" as \"阀门设置\",va.\"水损系数\"\
		FROM \"阀门\" va, ( \
			SELECT node.\"本点号\", node.\"高程\", node.\"基本需水量\", node.\"需水量模式\", node.\"横坐标\"\
			, node.\"纵坐标\", va.\"终止节点\"\
			FROM \"节点\" node, (\
				SELECT pipe.\"编号\", pipe.\"起始节点\", pipe.\"终止节点\", pipe.\"管长\", pipe.\"管径\"\
				, pipe.\"摩阻系数\"\
				FROM \"管段\" pipe\
				WHERE pipe.\"to_layer\" = '阀门'\
				) va\
			WHERE node.\"本点号\" = va.\"起始节点\"\
			) vnode \
		WHERE vnode.\"终止节点\" = va.\"本点号\"";

		if (!mDbConn->execSql(vaStartSql))
			return;

		std::vector<std::map<std::string, std::string>> valvesVec;
		mDbConn->queryResult(valvesVec);

		std::map<std::string, CivValve::ValveTable> valveTableMap;
		std::map<std::string, CivPipe::PipesTable> pipeTableMap;
		size_t valvsSize = valvesVec.size();
		for (int i = 0; i < valvsSize; i++)
		{
			std::map<std::string, std::string> valveMap = valvesVec[i];

			// 构造节点
			CivNode::NodeTable nodeTable;
			std::string szNo = valveMap.find("本点号")->second;
			nodeTable.ID = szNo;	
			nodeTable.Elev = valveMap.find("高程")->second;
			
			std::string patternID = valveMap.find("需水量模式")->second;
			std::string demand = valveMap.find("基本需水量")->second;
			handleDelayPattern(demand, patternID, nodeTable.Demand, nodeTable.PatternId);

			mNodeVec.push_back(nodeTable);

			// 节点坐标
			CivCoordinates::CoordTable coordTable;
			coordTable.ID = szNo;
			coordTable.XCoord = valveMap.find("横坐标")->second;
			coordTable.YCoord = valveMap.find("纵坐标")->second;

			mCoords.push_back(coordTable);
	
			std::string valveSn = valveMap.find("阀门本点号")->second;
			std::string valveType = valveMap.find("阀门类型")->second;
			
			if (valveType == "BV") // 止回阀，转成管段
			{
				CivPipe::Table pipeStruct;

				pipeStruct.ID = valveSn;
				pipeStruct.Node1 = szNo;
				pipeStruct.Length = "2";
				pipeStruct.Diameter = valveMap.find("阀门直径")->second;
				pipeStruct.Roughness =std::string("130");//valveMap.find("摩阻系数")->second;
				pipeStruct.Status = (valveMap.find("阀门状态")->second == "Open")?"Open":"CV";
				pipeStruct.MinorLoss = "0";

				auto pter = std::make_pair(valveSn, pipeStruct);
				pipeTableMap.insert(pter);
			}
			else
			{
				// 阀门
				CivValve::ValveTable valveTable;
				valveTable.ID = valveSn;
				valveTable.Node1 = szNo;
				valveTable.Diameter = valveMap.find("阀门直径")->second;
				valveTable.Type = valveType;
				valveTable.Setting = valveMap.find("阀门设置")->second;
				valveTable.MinorLoss = valveMap.find("水损系数")->second;

				valveTableMap.insert(std::make_pair(szNo, valveTable));

				// 阀门状态组件
				CivStatus::StatusTable statusTable;
				statusTable.ID = valveSn;
				statusTable.Setting = valveMap.find("固定状态")->second;
				
				mStatusVec.push_back(statusTable);
			}
			
		}

	//--构造阀门终止节点
	std::string vaEndSql =	"SELECT\
		'DW' || va.\"本点号\" AS \"本点号\", vnode.\"高程\", vnode.\"基本需水量\", vnode.\"需水量模式\"\
		, (va.\"横坐标\" + 1) AS \"横坐标\", (va.\"纵坐标\" + 1) AS \"纵坐标\", va.\"本点号\" as \"阀门本点号\",\
		va.\"类型\" as \"阀门类型\", ('DW' || va.\"本点号\") as \"阀门终止节点\"\
		FROM \"阀门\" va, (\
			SELECT node.\"本点号\", node.\"高程\", node.\"基本需水量\", node.\"需水量模式\", node.\"横坐标\"\
			, node.\"纵坐标\", va.\"起始节点\"\
			FROM \"节点\" node, (\
				SELECT pipe.\"编号\", pipe.\"起始节点\", pipe.\"终止节点\", pipe.\"管长\", pipe.\"管径\"\
				, pipe.\"摩阻系数\"\
				FROM \"管段\" pipe\
				WHERE pipe.\"from_layer\" = '阀门'\
				) va\
			WHERE node.\"本点号\" = va.\"终止节点\"\
			) vnode\
		WHERE vnode.\"起始节点\" = va.\"本点号\"";

	if (!mDbConn->execSql(vaEndSql))
		return;

	std::vector<std::map<std::string, std::string>> valvesEndVec;
	mDbConn->queryResult(valvesEndVec);

	size_t endVecSize = valvesEndVec.size();
	for (int i = 0; i < endVecSize; i++)
	{
		std::map<std::string, std::string> valveMap = valvesEndVec[i];

		// 构造节点
		CivNode::NodeTable nodeTable;
		std::string szNo = valveMap.find("本点号")->second;
		nodeTable.ID = szNo;
		nodeTable.Elev = valveMap.find("高程")->second;

		std::string patternID = valveMap.find("需水量模式")->second;
		std::string demand = valveMap.find("基本需水量")->second;
		handleDelayPattern(demand, patternID, nodeTable.Demand, nodeTable.PatternId);

		mNodeVec.push_back(nodeTable);

		// 节点坐标
		CivCoordinates::CoordTable coordTable;
		coordTable.ID = szNo;
		coordTable.XCoord = valveMap.find("横坐标")->second;
		coordTable.YCoord = valveMap.find("纵坐标")->second;

		mCoords.push_back(coordTable);

		std::string valveSn = valveMap.find("阀门本点号")->second;
		std::string valveType = valveMap.find("阀门类型")->second;

		if (valveType == "BV") // 止回阀，转成管段
		{
			auto iter = pipeTableMap.find(valveSn);
			if (iter != pipeTableMap.end())
			{
				pipeTableMap[valveSn].Node2 = szNo;
				mPipesVec.push_back(iter->second);
			}
		}
		else
		{
			// 阀门
			auto iter = valveTableMap.find(valveSn);
			if (iter != valveTableMap.end())
			{
				valveTableMap[valveSn].Node2 = szNo;
				mValuvesVec.push_back(iter->second);
			}
		}
	}
}