#include "CivTrackingAnalysis.h"
#include "CivSimulResultCache.h"
#include "CivHydrSimulation.h"
#include "CivInpConvertor.h"
#include "CivInpDbHelper.h"
#include "CivSysLog.h"

CivTrackingAnalysis::CivTrackingAnalysis(const std::string& uri)
	:mGraph(new ALGraph<CivGraphJunction, CivGraphEdage>()),mUri(uri)
{

}

CivTrackingAnalysis::~CivTrackingAnalysis()
{
	delete mGraph;
}

bool CivTrackingAnalysis::createGraphFrom()
{
	CivInpConvertor convertor(mUri);
	std::string inpFile = convertor.convertAnalysisInp();
	if (inpFile.empty())
		return false;

	CivHydrCompute dyCompute;
	if (!dyCompute.hdyrCompute())
		return false;

	NodeResultItems nodeItems;
	LinkResultItems linkItems;
	dyCompute.getNodeItemByInterval(0, nodeItems);
	dyCompute.getPipeItemByInterval(0, linkItems);

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

	// 顶点坐标
	CivCoordinates coords;
	CivInpDbHelper helper(mUri);
	helper.getCoordinates(coords);
	helper.getSnToCode(mSnToCodeMap);

	std::list<CivCoordinates::CoordTable> coordTableLis = coords.mTables;
	std::list<CivCoordinates::CoordTable>::iterator iter;
	for (iter = coordTableLis.begin(); iter != coordTableLis.end(); iter++)
	{
		CivCoordinates::CoordTable coordTable = *iter;

		// 插入顶点数据
		CivGraphJunction graphJunction(coordTable.code, coordTable.XCoord, coordTable.YCoord);
		auto iter = nodeItems.find(coordTable.ID);
		if (iter != nodeItems.end())
		{
			graphJunction.setHead(iter->second.dHead);
		}
		mGraph->insertAVertex(graphJunction);
	}

	// 管段
	CivPipe civPipe;
	helper.getPipe(civPipe);

	std::list<CivPipe::PipesTable> pipesTableLis = civPipe.mTables;
	std::list<CivPipe::PipesTable>::iterator pIter;

	for (pIter = pipesTableLis.begin(); pIter != pipesTableLis.end(); pIter++)
	{
		CivPipe::PipesTable pipeTable = *pIter;
		
		auto iter = mSnToCodeMap.find(pipeTable.Node1);
		if (iter == mSnToCodeMap.end())
		{
			continue;
		}
		std::string startcode = iter->second;
		// 获取管段起点坐标
		CivGraphJunction graphJunction1(startcode);
		int index1 = mGraph->getVertexIndex(graphJunction1);

		CivGraphJunction sStartjuction = mGraph->getData(index1);

		auto endCodeiter = mSnToCodeMap.find(pipeTable.Node2);
		if (endCodeiter == mSnToCodeMap.end())
		{
			continue;
		}
		std::string endcode = endCodeiter->second;
		// 获取管段终点坐标值
		CivGraphJunction graphJunction2(endcode);
		int index2 = mGraph->getVertexIndex(graphJunction2);
		CivGraphJunction endJunction = mGraph->getData(index2);


		if (sStartjuction.getHead() > endJunction.getHead())
		{
			CivGraphEdage edAge(pipeTable.code, pipeTable.Length, { sStartjuction.getXCoord(),sStartjuction.getYCoord(),endJunction.getXCoord(),endJunction.getYCoord() });
			mGraph->insertAEdge(sStartjuction, endJunction, edAge);
		}
		else if (sStartjuction.getHead() == endJunction.getHead())
		{
			CivGraphEdage edAge1(pipeTable.code, pipeTable.Length, { sStartjuction.getXCoord(),sStartjuction.getYCoord(),endJunction.getXCoord(),endJunction.getYCoord() });
			mGraph->insertAEdge(sStartjuction, endJunction, edAge1);

			CivGraphEdage edAge2(pipeTable.code, pipeTable.Length, { endJunction.getXCoord(),endJunction.getYCoord(), sStartjuction.getXCoord(),sStartjuction.getYCoord() });
			mGraph->insertAEdge(endJunction, sStartjuction, edAge2);

		}
		else
		{
			CivGraphEdage edAge(pipeTable.code, pipeTable.Length, { endJunction.getXCoord(),endJunction.getYCoord(), sStartjuction.getXCoord(),sStartjuction.getYCoord() });
			mGraph->insertAEdge(endJunction, sStartjuction, edAge);
		}

	}
	return true;
}

bool CivTrackingAnalysis::transformJson(const std::vector<CivGraphJunction>& junctions,
	const std::vector<CivGraphEdage>& pipes, std::string& jsonResult)
{
	// 管段
	size_t pipesTotal = pipes.size();
	if (pipesTotal <= 0)
		return false;

	jsonResult.append("[");
	
	for (int i = 0; i < pipesTotal; i++)
	{
		CivGraphEdage edge = pipes[i];

		if (edge.getSN().empty())
			continue;

		jsonResult.append("[[");
		jsonResult.append(edge.getStartX());
		jsonResult.append(",");
		jsonResult.append(edge.getStartY());
		jsonResult.append("],[");
		jsonResult.append(edge.getEndX());
		jsonResult.append(",");
		jsonResult.append(edge.getEndY());
		jsonResult.append("]],");
	}
	jsonResult = jsonResult.substr(0, jsonResult.length() - 1);
	jsonResult.append("]");

	return true;
}

bool CivTrackingAnalysis::upstreamTracking(const std::string& sN, std::string& jsonResult)
{	
	CivSysLog::getInstance()->info("上游追踪:" + sN, "CivTrackingAnalysis", __FUNCTION__);
	std::vector<CivGraphJunction> junctions;
	std::vector<CivGraphEdage> edges;
	
	if (!upstreamTracking(sN, junctions, edges))
	{
		CivSysLog::getInstance()->error("追踪失败", "CivTrackingAnalysis", __FUNCTION__);
		return false;
	}

	// 将查询到的信息拼接成字符串
	if (!transformJson(junctions, edges, jsonResult))
	{
		CivSysLog::getInstance()->error("转字符串失败", "CivTrackingAnalysis", __FUNCTION__);
		return false;
	}
	CivSysLog::getInstance()->info("追踪成功", "CivTrackingAnalysis", __FUNCTION__);
	return true;
}

bool CivTrackingAnalysis::downstreamTracking(const std::string& sN, std::string& jsonResult)
{
	std::vector<CivGraphJunction> junctions;
	std::vector<CivGraphEdage> edges;
	CivSysLog::getInstance()->info("下游追踪:" + sN, "CivTrackingAnalysis", __FUNCTION__);
	if (!downstreamTracking(sN, junctions, edges))
	{
		CivSysLog::getInstance()->error("追踪失败", "CivTrackingAnalysis", __FUNCTION__);
		return false;
	}

	// 将查询到的信息拼接成字符串
	if (!transformJson(junctions, edges,jsonResult))
	{
		CivSysLog::getInstance()->error("转字符串失败", "CivTrackingAnalysis", __FUNCTION__);
		return false;
	}
	return true;
}

bool CivTrackingAnalysis::waterSupplyScopeAnalysis(const std::string& sN, std::string& jsonResult)
{

	return true;
}

bool CivTrackingAnalysis::upstreamTracking(const std::string& sN,
	std::vector<CivGraphJunction>& junctions,
	std::vector<CivGraphEdage>& pipes)
{
	
	// 上溯，图反向
	ALGraph<CivGraphJunction, CivGraphEdage>* graph = mGraph->reverseGraph();
	
	CivGraphJunction junction(sN);
	graph->getVisitedResult(junction, junctions, pipes);

	delete graph;
	return true;
}

bool CivTrackingAnalysis::downstreamTracking(const std::string& sN,
	std::vector<CivGraphJunction>& junctions,
	std::vector<CivGraphEdage>& pipes)
{

	CivGraphJunction junction(sN);
	mGraph->getVisitedResult(junction, junctions, pipes);

	return true;
}

bool CivTrackingAnalysis::waterSupplyScopeAnalysis(const std::string& sN,
	std::vector<CivGraphJunction>& junctions,
	std::vector<CivGraphEdage>& pipes)
{

	return true;
}