#include "StdAfx.h"
#include "Wire.h"
#include "Node.h"

CWire::CWire(int nIn, int nOut, AnchorList &anchors, CCommonObject* from, int nFromID, CCommonObject *to, int nToID, CString strName) 
: CCommonObject(nIn, nOut, strName, CStringA())
{
	m_nObjType = 4;
	m_gPath = new GraphicsPath();
	m_pPen = new Pen(Color(0,0,0), 0.25);
	m_pBrush = new SolidBrush((ARGB)Color::Black);
	m_nIn = nIn;
	m_nOut = nOut;
	m_pStartNode = NULL;
	m_pEndNode = NULL;
	m_nMovementDir = -1;
	m_bMoveParts = true;
	int nSize = (int)anchors.GetSize();
	//Point *pnts = new Point[nSize];

	// copy anchors
	POSITION pos = anchors.GetHeadPosition();
	m_Points = new Point[nSize];
	for(int i=0; i<nSize; i++){
		m_Anchors.AddTail(anchors.GetNext(pos));
		m_Points[i].X = m_Anchors.GetTail().m_PointMain.x;
		m_Points[i].Y = m_Anchors.GetTail().m_PointMain.y;
	}
	m_gPath->AddLines(m_Points, nSize);
	if(from)
	{
		ConnectNode(from, true);
	}
	if(to)
	{
		ConnectNode(to, false);
	}
}

CWire::~CWire(void)
{
}

void CWire::ConnectNode(CCommonObject *node, bool bStart)
{
	Anchor a1, a2;
	if(bStart)
	{
		POSITION headPos = m_Anchors.GetHeadPosition();
		a1 = m_Anchors.GetNext(headPos);
		a2 = m_Anchors.GetNext(headPos);
	}else{
		POSITION tailPos = m_Anchors.GetTailPosition();
		a1 = m_Anchors.GetPrev(tailPos);
		a2 = m_Anchors.GetPrev(tailPos);
	}
	dynamic_cast<CNode *>(node)->ConnectWire(this, GetDirection(a2.m_PointMain, a1.m_PointMain));
	if(bStart)
	{
		m_pStartNode = node;
	}else
	{
		m_pEndNode = node;
	}
}

void CWire::OutScreen(Graphics &g)
{
	g.DrawPath(m_pPen, m_gPath);
/*	CRect rectIn = m_Connection.m_rectIns[0];
	CRect rectOut = m_Connection.m_rectOuts[0];
	rectIn.InflateRect(-2,-2);
	rectOut.InflateRect(-2,-2);
	Rect rectIn1, rectOut1;
	rectIn1.X = rectIn.left;
	rectIn1.Y = rectIn.top;
	rectIn1.Width = rectIn.Width();
	rectIn1.Height = rectIn.Height();

	rectOut1.X = rectOut.left;
	rectOut1.Y = rectOut.top;
	rectOut1.Width = rectOut.Width();
	rectOut1.Height = rectOut.Height();

	g.FillRectangle(m_pBrush, rectIn1);
	g.FillRectangle(m_pBrush, rectOut1);*/
}

void CWire::ResetGatePath()
{
	SAFE_DELETE(m_gPath);
	SAFE_DELETE_ARRAY(m_Points);
	m_gPath = new GraphicsPath();
}

void CWire::TransformCObject(Matrix* pMat)
{
	SAFE_DELETE_ARRAY(m_Points);
	m_gPath->Transform(pMat);
	int nSize = (int)m_Anchors.GetSize();
	m_Points = new Point[nSize];
	POSITION pos = m_Anchors.GetHeadPosition();
	for(int i=0; i<nSize; i++){
		m_Points[i].X = m_Anchors.GetAt(pos).m_PointMain.x;
		m_Points[i].Y = m_Anchors.GetNext(pos).m_PointMain.y;
	}
	pMat->TransformPoints(m_Points, nSize);
	pos = m_Anchors.GetHeadPosition();
	for(int i=0; i<nSize; i++){
		m_Anchors.GetAt(pos).m_PointMain.x = m_Points[i].X;
		m_Anchors.GetNext(pos).m_PointMain.y = m_Points[i].Y;
	}
	CPoint *pHead = &m_Anchors.GetHead().m_PointMain;
	CPoint *pTail = &m_Anchors.GetTail().m_PointMain;
/*	m_Connection.m_rectIns[0].SetRect(pHead->x-4, pHead->y-4, pHead->x+4, pHead->y+4);
	m_Connection.m_rectOuts[0].SetRect(pTail->x-4, pTail->y-4, pTail->x+4, pTail->y+4);*/

	//m_Connection.m_rectOuts[0].SetRect(m_Anchors[size-1].m_PointMain.x-4,m_Anchors[size-1].m_PointMain.y-4, m_Anchors[size-1].m_PointMain.x+4, m_Anchors[size-1].m_PointMain.y+4);
	//m_Connection.m_rectIns[0].SetRect(m_Anchors[0].m_PointMain.x-4,m_Anchors[0].m_PointMain.y-4, m_Anchors[0].m_PointMain.x+4, m_Anchors[0].m_PointMain.y+4);
}

void CWire::UpdateGraphicsPath()
{
	SAFE_DELETE_ARRAY(m_Points);
	POSITION pos = m_Anchors.GetHeadPosition();
	int nSize = (int)m_Anchors.GetSize();
	m_Points = new Point[nSize];
	for(int i=0; i<nSize; i++){
		m_Points[i].X = m_Anchors.GetAt(pos).m_PointMain.x;
		m_Points[i].Y = m_Anchors.GetNext(pos).m_PointMain.y;
	}
/*	CPoint headPoint = this->m_Anchors.GetHead().m_PointMain;
	CPoint tailPoint = this->m_Anchors.GetTail().m_PointMain;
	m_Connection.m_rectIns[0].SetRect(headPoint.x-4, headPoint.y-4, headPoint.x+4, headPoint.y+4);
	m_Connection.m_rectOuts[0].SetRect(tailPoint.x-4, tailPoint.y-4, tailPoint.x+4, tailPoint.y+4);*/
	SAFE_DELETE(m_gPath);
	m_gPath = new GraphicsPath();
	m_gPath->AddLines(m_Points, nSize);
}

bool CWire::HitTest(CPoint point)
{
	if (m_gPath->IsOutlineVisible(point.x, point.y, m_pPen)) //|| m_gPath->IsVisible(Point(point.x, point.y)))
		return true;
	return false;
}

CCommonObject* CWire::ConnectHitTest(CPoint point, int &nNumber)
{
	if(m_gPath->IsOutlineVisible(Point(point.x, point.y), m_pPen)){
		nNumber = 1; // just to know that we've hit something
		return this;
	}
	nNumber = 0;
	return NULL;
}

int CWire::GetDirection(CPoint p1, CPoint p2)
{
	if(p1.x < p2.x){
		return 0;
	}
	if(p1.y < p2.y){
		return 1;
	}
	if(p1.x > p2.x){
		return 2;
	}
	if(p1.y > p2.y){
		return 3;
	}
	return -1;
}


int CWire::GetDirAtPoint(CPoint point)
{
	int nSize = (int)m_Anchors.GetSize();
	POSITION pos = m_Anchors.GetHeadPosition();
	for(int i = 0; i < nSize - 1; i++){
		CPoint &p1 = m_Anchors.GetNext(pos).m_PointMain;
		CPoint &p2 = m_Anchors.GetAt(pos).m_PointMain;
		if(p1.x == point.x && p2.x == point.x){
			if(p1.y > point.y && p2.y < point.y){
				return 0;
			}
			if(p1.y < point.y && p2.y > point.y){
				return 0;
			}
			if(p1.y == point.y || p2.y == point.y){
				return 2;
			}
		}
		else if(p1.y == point.y && p2.y == point.y){
			if(p1.x > point.x && p2.x < point.x){
				return 1;
			}
			if(p1.x < point.x && p2.x > point.x){
				return 1;
			}
			if(p1.x == point.x || p2.x == point.x){
				return 2;
			}
		}
	}
	return -1;
}

void CWire::GetAnchorPairAtPoint(CPoint point, int *first, int *second)
{
	int nSize = (int)m_Anchors.GetSize();
	POSITION pos = m_Anchors.GetHeadPosition();
	double minDistance;
	int minIndex = -1;
	for(int i = 0; i < nSize - 1; i++)
	{
		CPoint &p1 = m_Anchors.GetNext(pos).m_PointMain;
		CPoint &p2 = m_Anchors.GetAt(pos).m_PointMain;
		if(p1.x == point.x && p1.y == point.y)
		{
			*first = i;
			*second = -1;
			return;
		}
		if(p1.x == point.x && p2.x == point.x)
		{
			if((p1.y > point.y && p2.y < point.y) || (p1.y < point.y && p2.y > point.y))
			{
				*first = i;
				*second = i+1;
				return;
			}
		}else if(p1.y == point.y && p2.y == point.y)
		{
			if((p1.x > point.x && p2.x < point.x) || (p1.x < point.x && p2.x > point.x))
			{
				*first = i;
				*second = i+1;
				return;
			}
		}else
		{
			//lines not containing point
			//or non horizontal or vertical lines		
		}
	}
	first = NULL;
	second = NULL;
}

void CWire::ExpandInsCount()
{
/*	bool *bInvIn = new bool[m_nIn+1];
	CCommonObject **pObjIn = new CCommonObject*[m_nIn+1];
	CRect *rectIns = new CRect[m_nIn+1];

	for(int i=0; i<m_nIn; i++){
		bInvIn[i] = m_Connection.m_pbInvIn[i];
		pObjIn[i] = m_Connection.m_pObjectIn[i];
		rectIns[i] = m_Connection.m_rectIns[i];
	}
	SAFE_DELETE_ARRAY(m_Connection.m_pbInvIn);
	SAFE_DELETE_ARRAY(m_Connection.m_pObjectIn);
	SAFE_DELETE_ARRAY(m_Connection.m_rectIns);

	m_Connection.m_pbInvIn = bInvIn;
	m_Connection.m_pObjectIn = pObjIn;
	m_Connection.m_rectIns = rectIns;

	m_Connection.m_pbInvIn[m_nIn] = false;
	m_Connection.m_pObjectIn[m_nIn] = NULL;
	m_Connection.m_rectIns[m_nIn].SetRectEmpty();
	m_nIn++;*/
}

void CWire::ExpandOutsCount()
{
/*	bool *bInvOut = new bool[m_nOut+1];
	CCommonObject **pObjOut = new CCommonObject*[m_nOut+1];
	CRect *rectOuts = new CRect[m_nOut+1];

	for(int i=0; i<m_nOut; i++){
		bInvOut[i] = m_Connection.m_pnInvOut[i];
		pObjOut[i] = m_Connection.m_pObjectOut[i];
		rectOuts[i] = m_Connection.m_rectOuts[i];
	}
	SAFE_DELETE_ARRAY(m_Connection.m_pnInvOut);
	SAFE_DELETE_ARRAY(m_Connection.m_pObjectOut);
	SAFE_DELETE_ARRAY(m_Connection.m_rectOuts);

	m_Connection.m_pnInvOut = bInvOut;
	m_Connection.m_pObjectOut = pObjOut;
	m_Connection.m_rectOuts = rectOuts;

	m_Connection.m_pnInvOut[m_nOut] = false;
	m_Connection.m_pObjectOut[m_nOut] = NULL;
	m_Connection.m_rectOuts[m_nOut].SetRectEmpty();
	m_nOut++;*/
}

void CWire::DrawAnchors(CDC *pDC)
{
	int nSize = (int)m_Anchors.GetSize();
	CPoint *pnt = NULL;
	POSITION pos = m_Anchors.GetHeadPosition();
	for(int i=0; i<nSize; i++){
		pnt = &m_Anchors.GetNext(pos).m_PointMain;
		pDC->Rectangle(pnt->x-4, pnt->y-4, pnt->x+4, pnt->y+4);
		//pDC->Rectangle(m_Anchors[i].m_PointMain.x - 4, m_Anchors[i].m_PointMain.y - 4, m_Anchors[i].m_PointMain.x + 4, m_Anchors[i].m_PointMain.y + 4);
	}
}

void CWire::PrepareForEdit(CPoint &point)
{
	if(!m_bMoveParts)
		return;
	m_nMovementDir = -1;
	m_aEditAnchors = new Anchor*[2];
	m_posEditAnchors = new POSITION[2];
	m_aEditAnchors[0] = m_aEditAnchors[1] = NULL;
	int nSize = (int)m_Anchors.GetSize();
	POSITION pos = m_Anchors.GetHeadPosition();
	Anchor *firstAnchor = NULL;
	Anchor *secondAnchor = NULL;
	bool bToSet = false;
	for(int i=0; i<nSize; i++){
		m_posEditAnchors[0] = pos;
		firstAnchor = &m_Anchors.GetNext(pos);
		if(pos){
			m_posEditAnchors[1] = pos;
			secondAnchor = &m_Anchors.GetAt(pos);
			if(firstAnchor->m_PointMain.x == secondAnchor->m_PointMain.x && point.x == firstAnchor->m_PointMain.x){
				int nLower;
				// problem with two vertical lines one below another - need to figure out which do we want to move
				// which one is lower? (y coord)
				firstAnchor->m_PointMain.y < secondAnchor->m_PointMain.y ? nLower = 0 : nLower = 1;
				// and is our clicked point between these two y coords?
				if(nLower){
					if(point.y < firstAnchor->m_PointMain.y && point.y > secondAnchor->m_PointMain.y)
						bToSet = true;
				}
				else{
					if(point.y > firstAnchor->m_PointMain.y && point.y < secondAnchor->m_PointMain.y)
						bToSet = true;
				}
				if(bToSet){
					m_nMovementDir = 0; // horizontal movement
					m_aEditAnchors[0] = new Anchor(firstAnchor->m_PointMain);
					m_aEditAnchors[1] = new Anchor(secondAnchor->m_PointMain);
					return;
				}
			}
			// the same with vertical lines
			else if(firstAnchor->m_PointMain.y == secondAnchor->m_PointMain.y && point.y == firstAnchor->m_PointMain.y){

				int nLefter; // :)
				firstAnchor->m_PointMain.x < secondAnchor->m_PointMain.x ? nLefter = 0 : nLefter = 1;
				if(nLefter){
					if(point.x < firstAnchor->m_PointMain.x && point.x > secondAnchor->m_PointMain.x)
						bToSet = true;
				}
				else{
					if(point.x > firstAnchor->m_PointMain.x && point.x < secondAnchor->m_PointMain.x)
						bToSet = true;
				}
				if(bToSet){
					m_nMovementDir = 1; // vertical movement
					m_aEditAnchors[0] = new Anchor(firstAnchor->m_PointMain);
					m_aEditAnchors[1] = new Anchor(secondAnchor->m_PointMain);
					return;
				}
			}
		}
	}
}

void CWire::PrepareForEditEdge(int nWhich)
{
	Anchor *firstAnchor = NULL;
	Anchor *lastAnchor = NULL;
	m_aEditAnchors = new Anchor*[2];
	m_posEditAnchors = new POSITION[2];
	POSITION pos;
	if(nWhich == 1){
	pos = m_Anchors.GetHeadPosition();
	if(pos){
		m_posEditAnchors[0] = pos;
		m_posEditAnchors[1] = pos;
		firstAnchor = &m_Anchors.GetNext(pos);
	}
	else{
		firstAnchor = NULL;
	}
	}
	else if(nWhich == 2){
	pos = m_Anchors.GetTailPosition();
	if(pos){
		m_posEditAnchors[0] = pos;
		m_posEditAnchors[1] = pos;
		lastAnchor = &m_Anchors.GetPrev(pos);
	}
	else{
		lastAnchor = NULL;
	}
	}
	m_nMovementDir = 1;
	if(nWhich == 1){ // editing first (head) anchor
		if(firstAnchor){
			m_aEditAnchors[0] = new Anchor(firstAnchor->m_PointMain);
			m_aEditAnchors[1] = new Anchor(firstAnchor->m_PointMain);
			//m_aEditAnchors[1] = new Anchor(secondAnchor->m_PointMain);
		}
	}
	else if(nWhich == 2){ // editing last (tail) anchor
		if(lastAnchor){
			m_aEditAnchors[0] = new Anchor(lastAnchor->m_PointMain);
			m_aEditAnchors[1] = new Anchor(lastAnchor->m_PointMain);
			//m_aEditAnchors[1] = new Anchor(semifinalAnchor->m_PointMain);
		}
	}
}

void CWire::MoveAnchorPair(CPoint &point)
{
	if(!m_bMoveParts)
		return;
	m_aEditAnchors[0]->MoveAnchor(point, m_nMovementDir);
	m_aEditAnchors[1]->MoveAnchor(point, m_nMovementDir);
}

void CWire::MoveAnchorEdge(CPoint &point)
{
	m_aEditAnchors[1]->MoveAnchor(RestrictPoint(point, m_aEditAnchors[0]->m_PointMain), m_nMovementDir);
}

void CWire::DrawMovedEdge(CDC *pDC)
{
	if(!m_bMoveParts)
		return;
	if(m_nMovementDir > -1){ // horizontal || vertical movement
		if(m_aEditAnchors[0] && m_aEditAnchors[1]){
			pDC->MoveTo(m_aEditAnchors[0]->m_PointMain.x, m_aEditAnchors[0]->m_PointMain.y);
			pDC->LineTo(m_aEditAnchors[1]->m_PointMain.x, m_aEditAnchors[1]->m_PointMain.y);
		}
	}
}

void CWire::DrawMovedLine(CDC *pDC)
{
	if(!m_bMoveParts)
		return;
	if(m_nMovementDir > -1){ // horizontal || vertical movement
		if(m_Anchors.GetSize() && m_posEditAnchors[0] && m_posEditAnchors[1]){
			pDC->MoveTo(m_Anchors.GetAt(m_posEditAnchors[0]).m_PointMain.x, m_Anchors.GetAt(m_posEditAnchors[0]).m_PointMain.y);
			pDC->LineTo(m_aEditAnchors[0]->m_PointMain.x, m_aEditAnchors[0]->m_PointMain.y);
			pDC->LineTo(m_aEditAnchors[1]->m_PointMain.x, m_aEditAnchors[1]->m_PointMain.y);
			pDC->LineTo(m_Anchors.GetAt(m_posEditAnchors[1]).m_PointMain.x, m_Anchors.GetAt(m_posEditAnchors[1]).m_PointMain.y);
		}
	}
}

CPoint CWire::RestrictPoint(CPoint point, CPoint pntBase)
{
	// Restrict point to horizontal, vertical or diagonal with respect to pntBase
	CSize d = point - pntBase;
	int cxAbs = abs(d.cx);
	int cyAbs = abs(d.cy);

	bool bHandled = false;

	if (cxAbs > 2 * cyAbs){			//0 deg
		point.y = pntBase.y;
		bHandled = true;
		m_nMovementDir = 0;
	}
	else if(cyAbs > 2 * cxAbs){		//90 deg
		point.x = pntBase.x;
		bHandled = true;
		m_nMovementDir = 1;
	}
	
	return point;
}

void CWire::FinishWireEdgeEdit(bool bCommit)
{
	if(!bCommit){
		SAFE_DELETE_ARRAY(m_aEditAnchors);
		SAFE_DELETE(m_posEditAnchors);
		return;
	}
	// check for consistency - add new point if moving 'connected' anchor
	POSITION head = m_Anchors.GetHeadPosition();
	POSITION tail = m_Anchors.GetTailPosition();
	bool bDone0 = false;
	bool bDone1 = false;
	if(m_posEditAnchors[0] == tail && m_aEditAnchors[0]){
		m_Anchors.AddTail(Anchor(*m_aEditAnchors[1]));
		bDone0 = true;
	}
	else if(m_posEditAnchors[0] == head && m_aEditAnchors[0]){
		m_Anchors.AddHead(Anchor(*m_aEditAnchors[1]));
		bDone1 = true;
	}
	POSITION pos[3];
	Anchor *anch[3];
	int nSize = (int)m_Anchors.GetSize();
	if(nSize > 2){
		pos[0] = m_Anchors.GetHeadPosition();
		pos[1] = pos[0];
		m_Anchors.GetNext(pos[1]);
		pos[2] = pos[1];
		m_Anchors.GetNext(pos[2]);

		for(int i=0; i<nSize; i++){
			if(pos[2]){//pos[2] != tail && pos[0] != head){
				anch[0] = &m_Anchors.GetAt(pos[0]);
				anch[1] = &m_Anchors.GetAt(pos[1]);
				anch[2] = &m_Anchors.GetAt(pos[2]);
				if((anch[0]->m_PointMain.x == anch[1]->m_PointMain.x) && (anch[1]->m_PointMain.x == anch[2]->m_PointMain.x)){ // removing middle anchor
					m_Anchors.RemoveAt(pos[1]);
					pos[1] = pos[2];
					m_Anchors.GetNext(pos[2]);
				}
				else if((anch[0]->m_PointMain.y == anch[1]->m_PointMain.y) && (anch[1]->m_PointMain.y == anch[2]->m_PointMain.y)){ // removing middle anchor
					m_Anchors.RemoveAt(pos[1]);
					pos[1] = pos[2];
					m_Anchors.GetNext(pos[2]);
				}
				else{
					pos[0] = pos[1];
					pos[1] = pos[2];
					m_Anchors.GetNext(pos[2]);
				}
			}
		}
	}

	UpdateGraphicsPath();
	SAFE_DELETE_ARRAY(m_aEditAnchors);
	SAFE_DELETE(m_posEditAnchors);
}

void CWire::FinishWireEdit(bool bCommit)
{
	if(!m_bMoveParts)
		return;
	if(!bCommit){
		SAFE_DELETE_ARRAY(m_aEditAnchors);
		SAFE_DELETE(m_posEditAnchors);
		return;
	}
	// check for consistency - add new point if moving 'connected' anchor
	POSITION head = m_Anchors.GetHeadPosition();
	POSITION tail = m_Anchors.GetTailPosition();
	bool bDone0 = false;
	bool bDone1 = false;
	if(m_posEditAnchors[0] == head && m_aEditAnchors[0]){
		m_Anchors.InsertAfter(m_posEditAnchors[0], Anchor(m_aEditAnchors[0]->m_PointMain));
		bDone0 = true;
	}
	if(m_posEditAnchors[1] == tail && m_aEditAnchors[1]){
		m_Anchors.InsertBefore(m_posEditAnchors[1], Anchor(m_aEditAnchors[1]->m_PointMain));
		bDone1 = true;
	}
	if(!bDone0 && m_aEditAnchors[0])
		m_Anchors.GetAt(m_posEditAnchors[0]).m_PointMain = m_aEditAnchors[0]->m_PointMain;
	if(!bDone1 && m_aEditAnchors[1])
		m_Anchors.GetAt(m_posEditAnchors[1]).m_PointMain = m_aEditAnchors[1]->m_PointMain;

	if(m_aEditAnchors[0] && *m_aEditAnchors[0] == m_Anchors.GetHead()){
		m_Anchors.RemoveAt(m_posEditAnchors[0]);
	}
	if(m_aEditAnchors[1] && *m_aEditAnchors[1] == m_Anchors.GetTail()){
		m_Anchors.RemoveAt(m_posEditAnchors[1]);
	}
	POSITION pos[3];

	Anchor *anch[3];
	int nSize = (int)m_Anchors.GetSize();
	if(nSize > 2){
		pos[0] = m_Anchors.GetHeadPosition();
		pos[1] = pos[0];
		m_Anchors.GetNext(pos[1]);
		pos[2] = pos[1];
		m_Anchors.GetNext(pos[2]);

		for(int i=0; i<nSize; i++){
			if(pos[2]){//pos[2] != tail && pos[0] != head){
				anch[0] = &m_Anchors.GetAt(pos[0]);
				anch[1] = &m_Anchors.GetAt(pos[1]);
				anch[2] = &m_Anchors.GetAt(pos[2]);
				if((anch[0]->m_PointMain.x == anch[1]->m_PointMain.x) && (anch[1]->m_PointMain.x == anch[2]->m_PointMain.x)){ // removing middle anchor
					m_Anchors.RemoveAt(pos[1]);
					pos[1] = pos[2];
					m_Anchors.GetNext(pos[2]);
				}
				else if((anch[0]->m_PointMain.y == anch[1]->m_PointMain.y) && (anch[1]->m_PointMain.y == anch[2]->m_PointMain.y)){ // removing middle anchor
					m_Anchors.RemoveAt(pos[1]);
					pos[1] = pos[2];
					m_Anchors.GetNext(pos[2]);
				}
				else{
					pos[0] = pos[1];
					pos[1] = pos[2];
					m_Anchors.GetNext(pos[2]);
				}
			}
		}
	}

	UpdateGraphicsPath();
	SAFE_DELETE_ARRAY(m_aEditAnchors);
	SAFE_DELETE(m_posEditAnchors);
}

CCommonObject* CWire::Clone(CPoint TopLeftOrigin, CString strNewName, int nRotation)
{
	return this;
}


std::vector<CCommonObject *> CWire::GetConnectedObjs(bool in)
{
	std::vector<CCommonObject *> objs;
	CNode *node;
	if(in)
	{
		node = dynamic_cast<CNode *>(m_pStartNode);
	}else{
		node = dynamic_cast<CNode *>(m_pEndNode);
	}
	std::vector<CWire *> wires = node->GetWires();;
	for(std::vector<CWire *>::iterator i = wires.begin(); i != wires.end(); i++)
	{
		if(*i != this)
			objs.push_back(*i);
	}
	if(node->GetAttachedObject() != NULL)
	{
		objs.push_back(node->GetAttachedObject());
	}
	return objs;
}

void CWire::OutXml(stringstream &ss)
{
	CStringA strLevel = "\t\t";
	CStringA strLevel1 = strLevel + "\t";
	CStringA strLevel2 = strLevel1 + "\t";
	CStringA strLevel3 = strLevel2 + "\t";

	ss << strLevel << "<ELEM type=\"4\">" << endl;
	ss << strLevel1 << "<DISPLAY>" << (CStringA)m_strUniqueName << "</DISPLAY>" << endl;
	ss << strLevel1 << "<ORIGIN inProject=\"1\">Wire</ORIGIN>" << endl;
	
	ss << strLevel1 << "<NAME>" << (CStringA)m_strUniqueName << "</NAME>" << endl;
	ss << strLevel1 << "<POSITION tlx1=\"" << m_pointTopLeft.x << "\" tly1=\"" << m_pointTopLeft.y << "\"></POSITION>" << endl;

	std::vector<CCommonObject *> inObjs;
	std::vector<CCommonObject *> outObjs;
	for(int t = 0; t < 2; t++){
		if(t == 0)
		{
			inObjs = GetConnectedObjs(true);
		}else
		{
			outObjs = GetConnectedObjs(false);
		}
	}

	ss << strLevel1 << "<ANCHORS nIn=\"" << inObjs.size() << "\" nOut=\"" << outObjs.size() << "\">" << endl;

	POSITION pos = m_Anchors.GetTailPosition();
	CPoint *pPoint = NULL;
	while(pos){
		pPoint = &m_Anchors.GetPrev(pos).m_PointMain;
		if(pPoint){
			ss << strLevel2 << "<POINT x=\"" << pPoint->x << "\" y=\"" << pPoint->y << "\"></POINT>" << endl;
		}
	}
	ss << strLevel1 << "</ANCHORS>" << endl;
	ss << strLevel1 << "<CONNECTIONS>" << endl;

	for(int t = 0; t < 2; t++){
		std::vector<CCommonObject *> *p_objs;
		if(t == 0)
		{
			p_objs = &inObjs;
		}else
		{
			p_objs = &outObjs;
		}
		std::vector<CCommonObject *> &objs = *p_objs;
		ss << strLevel2 << (t == 0 ? "<INCONNECTIONS nCount=\"" : "<OUTCONNECTIONS nCount=\"" ) << objs.size() << "\">" << endl;
		int j = 0;
		for(int i=0; i<objs.size(); i++){
			ss << strLevel3 << (t == 0 ? "<IN Name=\"" : "<OUT Name=\"" ) << (CStringA)objs[i]->m_strUniqueName 
			<< "\">" << j++ << (t == 0 ? "</IN>" : "</OUT>") << endl;
		}
		ss << strLevel2 << (t == 0 ? "</INCONNECTIONS>" : "</OUTCONNECTIONS>") << endl;
	}

	ss << strLevel1 << "</CONNECTIONS>" << endl;
	ss << strLevel << "</ELEM>" << endl;
}

void CWire::DisconnectCObject(CCommonObject *pObject)
{
}

void CWire::Disconnect()
{
	dynamic_cast<CNode*>(m_pStartNode)->DisconnectWire(this);
	dynamic_cast<CNode*>(m_pEndNode)->DisconnectWire(this);
}


void CWire::SetConnection(bool bIn, int nPos, CCommonObject* pConnectTo)
{

}

int CWire::EditEdgePoint(CPoint point)
{
	Anchor first = m_Anchors.GetHead();
	Anchor last = m_Anchors.GetTail();
	if(first.m_PointMain == point){
		return 1;
	}
	if(last.m_PointMain == point){
		return 2;
	}
	return -1;
}

CCommonObject * CWire::Split(CPoint point, CWire **newWire)
{
	int firstAnchor;
	int secondAnchor;
	GetAnchorPairAtPoint(point, &firstAnchor, &secondAnchor);
	AnchorList newWireAnchors1;	
	AnchorList newWireAnchors2;
	int nSize = (int)m_Anchors.GetSize();
	POSITION pos = m_Anchors.GetHeadPosition();	
	for(int i = 0; i < nSize; i++)
	{
		Anchor a = m_Anchors.GetNext(pos);
		if(i <= firstAnchor)
		{
			newWireAnchors1.AddTail(a);
		}
		else
		{
			newWireAnchors2.AddTail(a);
		}
	}
	if(secondAnchor != -1)
	{
		newWireAnchors1.AddTail(Anchor(point));
	}
	newWireAnchors2.AddHead(Anchor(point));
	SetAnchors(newWireAnchors1);
	dynamic_cast<CNode *>(m_pEndNode)->DisconnectWire(this);
	CNode *newNode = new CNode(point);
	*newWire = new CWire(0, 0, newWireAnchors2, newNode, 0, m_pEndNode, 0, CString(""));
	ConnectNode(newNode, false);
	return newNode;
}

void CWire::SetAnchors(AnchorList &anchors)
{
	m_Anchors.RemoveAll();
	m_Anchors.AddTail(&anchors);
	UpdateGraphicsPath();
}

//------------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/////////////////Anchor - helper class for CWire class//////////////////////////
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------

Anchor::Anchor(CPoint point, CPoint *pointPrev) 
: m_PointMain(point), m_pPointPrev(pointPrev), m_pPointNext(NULL)
{
}

bool Anchor::operator==(const Anchor& a) const
{
	if(m_PointMain == a.m_PointMain)
		return true;
	return false;
}

bool Anchor::operator!=(const Anchor& a) const
{
	if(m_PointMain != a.m_PointMain)
		return true;
	return false;
}

const Anchor& Anchor::operator=(const Anchor& a)
{
	if(this != &a){
		m_PointMain = a.m_PointMain;
		m_pPointPrev = a.m_pPointPrev;
		m_pPointNext = a.m_pPointNext;
	}
	return *this;
}

void Anchor::MoveAnchor(CPoint &point, int nDirection)
{
	if(nDirection == 0){ // horizontal movement
		m_PointMain.x = point.x;
	}
	else if(nDirection == 1){ // vertical movement
		m_PointMain.y = point.y;
	}
	else {
		TRACE(_T("nDirection == -1, cannot move anchorpair\n"));
	}
}
