#include "CivHydrTableHelper.h"
#include "CivTableFields.h"

#include "CivCommonUtils.h"
#include "CivPgDbConnection.h"


CivHydrTableHelper::CivHydrTableHelper(const std::string& uri)
{
	mConn = new CivPgDbConnection();
	mConn->connect(uri);
}

CivHydrTableHelper::~CivHydrTableHelper()
{
	mConn->disconnect();
	delete mConn;
	mConn == nullptr;
}

bool CivHydrTableHelper::mainTain()
{
	//unTopoMaintain();

	// 管网组件
	updateAssem(TABLE_NODE, std::string("本点号"), "JD");
	updateAssem(TABLE_PIPE, std::string("编号"), "GD");
	updateAssem(TABLE_TANK, std::string("本点号"), "TK");
	updateAssem(TABLE_VALVE, std::string("本点号"), "VA");
	updateAssem(TABLE_RESERVOIR, std::string("本点号"), "RE");
	updateAssem(TABLE_PUMP, std::string("本点号"), "PU");

	// 方案管网组件
	updateAssem(PROJ_TABLE_NODE, std::string("本点号"), "PJD");
	updateAssem(PROJ_TABLE_PIPE, std::string("编号"), "PGD");
	updateAssem(PROJ_TABLE_TANK, std::string("本点号"), "PTK");
	updateAssem(PROJ_TABLE_VALVE, std::string("本点号"), "PVA");
	updateAssem(PROJ_TABLE_RESERVOIR, std::string("本点号"), "PRE");
	updateAssem(PROJ_TABLE_PUMP, std::string("本点号"), "PPU");

	if (!topoMaintain())
		return false;
	return true;
}

void CivHydrTableHelper::updateAssem(const std::string& table, const std::string& filed,const std::string& prefix)
{
	// 节点
	std::vector<std::map<std::string, std::string>> resVec;
	if (!mConn->query(table, { "id" }, resVec))
	{
		mErrInfo = mConn->getLastError();
		return;
	}
	
	if (resVec.size() <= 0)
		return;

	std::vector<std::string> sNs;
	CivCommonUtils::genSeqNo(prefix, resVec.size(), sNs);

	std::string sql = "update "+ table +" set "+ filed +" = tmp."+ filed +" from(values";
	for (int i = 0; i < sNs.size(); i++)
	{
		std::map<std::string,std::string> resMap = resVec[i];
		std::string id = resMap.find("id")->second;
		sql.append("(");
		sql.append(id);
		sql.append(",\'");
		sql.append(sNs[i]);
		sql.append("\'),");
	}
	sql = sql.substr(0, sql.length() - 1);
	sql += ") as tmp(id, \""+ filed +"\") where "+ table +".id = tmp.id; ";

	if (mConn && mConn->execSql(sql))
	{
		mErrInfo = mConn->getLastError();
		return;
	}
}

bool CivHydrTableHelper::topoMaintain()
{
	// 管段与
	topoMainTable(TABLE_PIPE, TABLE_NODE, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(TABLE_PIPE, TABLE_NODE, std::string("终止节点"), std::string("本点号"), std::string("to_code"));
	topoMainTable(TABLE_PIPE, TABLE_RESERVOIR, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(TABLE_PIPE, TABLE_TANK, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(TABLE_PIPE, TABLE_VALVE, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(TABLE_PIPE, TABLE_VALVE, std::string("终止节点"), std::string("本点号"), std::string("to_code"));

	topoMainTable(TABLE_PIPE, PROJ_TABLE_NODE, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(TABLE_PIPE, PROJ_TABLE_NODE, std::string("终止节点"), std::string("本点号"), std::string("to_code"));
	topoMainTable(TABLE_PIPE, PROJ_TABLE_RESERVOIR, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(TABLE_PIPE, PROJ_TABLE_TANK, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(TABLE_PIPE, PROJ_TABLE_VALVE, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(TABLE_PIPE, PROJ_TABLE_VALVE, std::string("终止节点"), std::string("本点号"), std::string("to_code"));

	topoMainTable(PROJ_TABLE_PIPE, TABLE_NODE, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(PROJ_TABLE_PIPE, TABLE_NODE, std::string("终止节点"), std::string("本点号"), std::string("to_code"));
	topoMainTable(PROJ_TABLE_PIPE, TABLE_RESERVOIR, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(PROJ_TABLE_PIPE, TABLE_TANK, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(PROJ_TABLE_PIPE, TABLE_VALVE, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(PROJ_TABLE_PIPE, TABLE_VALVE, std::string("终止节点"), std::string("本点号"), std::string("to_code"));

	topoMainTable(PROJ_TABLE_PIPE, PROJ_TABLE_NODE, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(PROJ_TABLE_PIPE, PROJ_TABLE_NODE, std::string("终止节点"), std::string("本点号"), std::string("to_code"));
	topoMainTable(PROJ_TABLE_PIPE, PROJ_TABLE_RESERVOIR, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(PROJ_TABLE_PIPE, PROJ_TABLE_TANK, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(PROJ_TABLE_PIPE, PROJ_TABLE_VALVE, std::string("起始节点"), std::string("本点号"), std::string("from_code"));
	topoMainTable(PROJ_TABLE_PIPE, PROJ_TABLE_VALVE, std::string("终止节点"), std::string("本点号"), std::string("to_code"));

	// 处理方案和阀门的拓扑关系
	topoLikelyPipe(TABLE_PIPE, TABLE_VALVE, std::string("起始节点"), std::string("to_code"));
	topoLikelyPipe(TABLE_PIPE, TABLE_VALVE, std::string("终止节点"), std::string("from_code"));

	topoLikelyPipe(PROJ_TABLE_PIPE, TABLE_VALVE, std::string("起始节点"), std::string("to_code"));
	topoLikelyPipe(PROJ_TABLE_PIPE, TABLE_VALVE, std::string("终止节点"), std::string("from_code"));

	topoLikelyPipe(TABLE_PIPE, PROJ_TABLE_VALVE, std::string("起始节点"), std::string("to_code"));
	topoLikelyPipe(TABLE_PIPE, PROJ_TABLE_VALVE, std::string("终止节点"), std::string("from_code"));

	return true;

}

bool CivHydrTableHelper::unTopoMaintain()
{
	unTopoTable(TABLE_NODE, {std::string("本点号")});
	unTopoTable(TABLE_PIPE, { std::string("编号"),std::string("起始节点"),std::string("终止节点") });
	unTopoTable(TABLE_RESERVOIR, { std::string("本点号")});
	unTopoTable(TABLE_TANK, { std::string("本点号") });
	unTopoTable(TABLE_VALVE, { std::string("本点号"),std::string("起始节点"),std::string("终止节点") });
	return true;
}

bool CivHydrTableHelper::topoMainTable(const std::string& sourceTable, 
	const std::string& targetTable, 
	const std::string& pipesn, 
	const std::string& nodeSn,
	const std::string& code)
{
	std::string sql = "UPDATE \"" + sourceTable + "\" \
		SET \"" + pipesn + "\" = cqt.\"" + nodeSn + "\" FROM \"" + targetTable + "\" cqt WHERE \
		 \""+sourceTable+"\".\"" + code + "\" = cqt.\"code\"";


	if (mConn && !mConn->execSql(sql))
	{
		mErrInfo = mConn->getLastError();
		return false;
	}

	return true;
}

bool CivHydrTableHelper::topoLikelyPipe(const std::string& pipeTable, const std::string& nodeTable, const std::string& filed, const std::string& tocode)
{
	std::string sql = "update \""+nodeTable+"\" as pu set \""+filed+"\" = \
		(select pipe.\"编号\" from \""+pipeTable+"\" as pipe  where pipe.\""+tocode+"\"=pu.\"code\")  where exists (select 1 from \""+pipeTable+"\" as pipe1 where pipe1.\""+tocode+"\"=pu.\"code\")";

	if (mConn && !mConn->execSql(sql))
	{
		mErrInfo = mConn->getLastError();
		return false;
	}

	return true;
}


bool CivHydrTableHelper::topoValve(const std::string& sn, 
	const std::string& fromcode, 
	const std::string& tocode)
{
	std::string sql = "update \"";
	sql.append(TABLE_VALVE); 
	sql.append("\" set \"" + sn + "\" = dd.\"本点号\"\
		from(select node.\"本点号\" \"本点号\", node.\"code\" \"nodecode\", tt.\"code\"  \"vacode\" from \
			\""+TABLE_NODE+"\" node, (select t2.\""+tocode+"\" \""+tocode+"\", t1.\"code\" \"code\" from \""+TABLE_PIPE+"\" t2, \""+TABLE_VALVE+"\" t1 where t2.\""+fromcode+"\" = t1.\"code\") tt\
			where node.\"code\" = tt.\""+tocode+"\") dd\
		where \"code\" = dd.\"vacode\"");


	if (mConn && !mConn->execSql(sql))
	{
		mErrInfo = mConn->getLastError();
		return false;
	}

	return false;
}

bool CivHydrTableHelper::unTopoTable(const std::string& table, const std::vector<std::string>& fields)
{
	if (fields.size() < 1)
	{
		mErrInfo = "fileds is empty";
		return false;
	}
		
	std::string sql = "update \""+ table +"\" set ";
	for (int i = 0; i < fields.size(); i++)
	{
		sql.append(fields[i]);
		sql.append("= null");
		sql.append(",");
	}
	sql = sql.substr(0, sql.length() - 1);

	
	if (mConn && !mConn->execSql(sql))
	{
		mErrInfo = mConn->getLastError();
		return false;
	}
	return false;
}


void CivHydrTableHelper::getCodeToSn(const std::string& code, std::string& sn)
{
	std::string sql = "select \"本点号\" from  节点 where code = '" + code+"'";

	if (mConn && !mConn->execSql(sql))
	{
		mErrInfo = mConn->getLastError();
		return;
	}

	std::vector<std::map<std::string, std::string>> res;
	mConn->queryResult(res);

	if (res.size() <= 0)
	{
		return;
	}

	sn = res[0].find("本点号")->second;
	return;
}
