#include "CivPumpHelper.h"
#include "CivPgDbConnection.h"
#include "StringUtils.h"
#include <set>

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

CivPumpHelper::~CivPumpHelper()
{
	mConn->disconnect();
	delete mConn;
}

void CivPumpHelper::getMap(const string& key, const string& val, map<string, string>& res)
{
	vector<map<string, string>> vecMap;
	if (!mConn->query(mTable, { key ,val }, vecMap))
		return;

	if (vecMap.size() <= 0)
		return;

	size_t total = vecMap.size();
	for (int i = 0; i < total; i++)
	{
		map<string, string> tempMap = vecMap[i];

		string keyVal = tempMap.find(key)->second;
		string valVal = tempMap.find(val)->second;

		res.insert(pair<string, string>(keyVal, valVal));
	}
}

int CivPumpHelper::getPumpNumbers()
{
	string sql = "select count(id) as cunt from " + mTable;
	if (!mConn->execSql(sql))
		return 0;

	vector<map<string,string>> pumpRes;
	if (!mConn->queryResult(pumpRes))
		return 0;

	if (pumpRes.size() <= 0)
		return 0;

	map<string, string> pumpMap = pumpRes[0];
	map<string, string>::iterator iter = pumpMap.find("cunt");
	if (iter == pumpMap.end())
		return 0;

	string pumpSize = iter->second;
	int pumps = atoi(pumpSize.c_str());
	return pumps;
}

void CivPumpHelper::getPumpSn(vector<string>& pumpNames,map<string,string>& pumpMap)
{
	const string sz = "本点号";
	vector<map<string, string>> vecMap;
	if (!mConn->query(mTable, { sz,"code" }, vecMap))
		return;

	if (vecMap.size() <= 0)
		return;

	size_t total = vecMap.size();
	for (int i = 0; i < total; i++)
	{
		map<string, string> tempMap = vecMap[i];
		string val = tempMap.find(sz)->second;
		string code = tempMap.find("code")->second;
		pumpNames.push_back(val);
		pumpMap.insert(pair<string, string>(val, code));
	}
}


void CivPumpHelper::getPumpStations(vector<PumpStation>& stations)
{
	vector<map<string, string>> vecMap;
	if (!mConn->query(mTable, { "本点号","code","价格模式","能量价格","功率","泵站","水泵状态","转速比" }, vecMap))
		return;

	if (vecMap.size() <= 0)
		return;

	size_t total = vecMap.size();
	map<string, vector<PumpStruct>> stationMap;

	for (int i = 0; i < total; i++)
	{
		map<string, string> tempMap = vecMap[i];
		
		PumpStruct pumpStruct;
		pumpStruct.sz = tempMap.find("本点号")->second;
		pumpStruct.pricePattern = tempMap.find("价格模式")->second;
		pumpStruct.power = tempMap.find("功率")->second;
		pumpStruct.status = tempMap.find("水泵状态")->second;
		pumpStruct.speedRatio = tempMap.find("转速比")->second;
		pumpStruct.code = tempMap.find("code")->second;

		string pumpStation = tempMap.find("泵站")->second;
		stationMap[pumpStation].push_back(pumpStruct);
	}

	// 构造泵站集合
	map<string, vector<PumpStruct>>::iterator iter = stationMap.begin();
	for (; iter != stationMap.end(); iter++)
	{
		PumpStation station;
		station.stationName = iter->first;
		station.pumps = iter->second;
		stations.push_back(station);
	}
}

void CivPumpHelper::getMonitors(vector<string>& monitors,map<string,string>& monitorMap)
{
	string sql = "select  node.\"本点号\",node.\"code\" from \"节点\" as node, \"压力监测点\" as ja where node.\"code\" = ja.\"节点id\"";

	if (!mConn->execSql(sql))
		return;

	vector<map<string, string>> tempMapVec;
	mConn->queryResult(tempMapVec);

	for (int i = 0; i < tempMapVec.size(); i++)
	{
		map<string, string> tempMap = tempMapVec[i];
		string szNo = tempMap.find("本点号")->second;
		string code = tempMap.find("code")->second;
		
		vector<string>::iterator iter = std::find(monitors.begin(), monitors.end(), code);
		if (iter != monitors.end())
		{
			*iter = szNo;
			monitorMap.insert(pair<string, string>(szNo,code));
		}
	}
}

bool CivPumpHelper::updateDatas(const std::string& tablename, 
	const std::map<std::string, std::map<std::string, float>>& resultMap)
{
	if (tablename.empty())
		return false;

	if (resultMap.size() <= 0)
		return false;

	bool resBool = true;
	std::map<std::string, std::map<std::string, float>>::const_iterator iter = resultMap.cbegin();

	// 缓存节点图层本点号和code 的映射
	std::map<std::string, std::string> snToCodeMap;
	snToCode("节点", snToCodeMap);

	for (; iter != resultMap.cend(); iter++)
	{
		std::string key = iter->first;
		std::map<std::string, float> resmap = iter->second;
		
		std::vector<std::string> dateStrVec;
		StringUtils::split(key, dateStrVec);

		std::string dateStr;
		if (dateStrVec.size() > 1)
			dateStr = dateStrVec[0];

		// 判断该条件下是否存在数据
		std::string sesql = "select \"id\" from "+tablename +"  where \"时间点\"='"+key+"'";
		if (!mConn->execSql(sesql))
			continue;

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

	
		if (vecMap.size() <= 0 || vecMap[0].size() < 0)
		{
			// 数据库没数据需要直接插入操作
			std::string sql = "INSERT INTO " + tablename + "(日期,时间点,code,余氯) VALUES";

			std::map<std::string, float>::const_iterator const_iter = resmap.cbegin();
			for (; const_iter != resmap.cend(); const_iter++)
			{
				std::string keyStr = const_iter->first;
				float valStr = const_iter->second;
				std::map<std::string, std::string>::iterator keyIter = snToCodeMap.find(keyStr);
				if (keyIter != snToCodeMap.end())
				{
					keyStr = keyIter->second;
				}
				else
				{
					continue;
				}
				sql.append("(");
				sql.append("'" + dateStr + "'");
				sql.append("'" + key + "'");
				sql.append("'" + keyStr + "'");
				sql.append(std::to_string(valStr));
				sql.append("),");
			}
			sql = sql.substr(0, sql.size() - 1);

			if (!mConn->execSql(sql))
			{
				resBool = false;
				break;
			}		
		}
		else // 数据库存在数据则需要更新
		{
			std::string sql = "update " + tablename +" set  \"余氯\" =  data_table.vals ";

			std::map<std::string, float>::const_iterator const_iter = resmap.cbegin();
			std::string codeArr = "array[";
			std::string valArr = "array[";
			std::string timeArr = "array[";
			for (; const_iter != resmap.cend(); const_iter++)
			{
				std::string keyStr = const_iter->first;
				float valStr = const_iter->second;

				std::map<std::string, std::string>::iterator keyIter = snToCodeMap.find(keyStr);
				if (keyIter != snToCodeMap.end())
				{
					keyStr = keyIter->second;
				}
				else
				{
					continue;
				}

				// 编码
				codeArr.append("'" + keyStr + "',");

				// 值
				valArr.append(std::to_string(valStr) + ",");
			}
			std::string codeArrStr = codeArr.substr(0, codeArr.length() - 1);
			std::string valArrStr = valArr.substr(0, valArr.length() - 1);

			codeArrStr.append("]");
			valArrStr.append("]");


			sql.append("from (select unnest(");	
			sql.append(codeArrStr);
			sql.append(") as codes,");

			// 拼接余氯值
			sql.append("unnest(");
			sql.append(valArrStr);
			sql.append(") as vals) as data_table");

			sql.append(" where "+tablename+".\"时间点\" = ' "+key+"'");
			sql.append(" and  "+ tablename+".\"code\" = data_table.codes");

			if (!mConn->execSql(sql))
			{
				resBool = false;
				break;
			}
		}
	}	

	return resBool;
}

void CivPumpHelper::codeToSn(const std::string& tablename, 
	std::map<std::string, std::string>& resmap)
{
	baseCommonCache(tablename, resmap, CodeToSn);
}

void CivPumpHelper::snToCode(const std::string& tablename, 
	std::map<std::string, std::string>& resmap)
{
	baseCommonCache(tablename, resmap, SnToCode);
}

void CivPumpHelper::baseCommonCache(const std::string& tablename, std::map<std::string, std::string>& resmap, CacheType cacheType)
{
	std::string sql;
	if (tablename == "管段")
	{
		sql = "select \"编号\",\"code\" from  " + tablename;
	}
	else
	{
		sql = "select \"本点号\",\"code\" from  " + tablename;
	}

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

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

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

	// 
	int total = res.size();
	for (int i = 0; i < total; i++)
	{
		std::map<std::string, std::string> resultMap = res[i];
		std::map<std::string, std::string>::const_iterator const_iter = resultMap.cbegin();

		std::string key;
		std::string val;
		for (; const_iter != resultMap.cend(); const_iter++)
		{
			if(const_iter->first == "code")
				key = const_iter->second;
			else
				val = const_iter->second;
		}
		switch (cacheType)
		{
		case CodeToSn:
			resmap.insert(std::pair<std::string, std::string>(key, val));
			break;
		case SnToCode:
			resmap.insert(std::pair<std::string, std::string>(val, key));
			break;
		default:
			break;
		}
	}
	return;
}