#include "StdAfx.h"
#include "Inv.h"

CInv::CInv(CPoint TopLeftOrigin, CString strName)
	: CCommonObject(1, 1, strName, "Invertor")
{
	m_gPath = NULL;
	m_nObjType = 6;
	m_pointTopLeft = TopLeftOrigin;
	m_pointTL.X = 0;
	m_pointTL.Y = 0;
	
	m_Connection.m_rectOuts[0] = new CRect(0,0,0,0);
	m_Connection.m_rectOuts[0].InflateRect(4,4);
	m_Connection.m_rectIns[0] = new CRect(-30,0,-30,0);
	m_Connection.m_rectIns[0].InflateRect(4,4);

	m_pPen = new Pen(Color(0,0,0), 0.25);
	
	CreateGPath();

	GetBounds();
	Matrix *pMat = new Matrix();
	pMat->Translate((REAL)m_pointTopLeft.x, (REAL)m_pointTopLeft.y);
	TransformCObject(pMat);
	SAFE_DELETE(pMat);
}

CInv::~CInv()
{
	SAFE_DELETE_ARRAY(m_Connection.m_pbInvIn);
	SAFE_DELETE_ARRAY(m_Connection.m_pnInvOut);
	//SAFE_DELETE_ARRAY(*m_Connection.m_pObjectIn);
	//SAFE_DELETE_ARRAY(*m_Connection.m_pObjectOut);
	SAFE_DELETE(m_Connection.m_pObjectIn);
	SAFE_DELETE(m_Connection.m_pObjectOut);
	SAFE_DELETE_ARRAY(m_Connection.m_rectIns);
	SAFE_DELETE_ARRAY(m_Connection.m_rectOuts);
	SAFE_DELETE(m_pPen);
	SAFE_DELETE(m_gPath);
}


CCommonObject* CInv::Clone(CPoint TopLeftOrigin, CString strNewName, int nRotation)
{
	CInv *pNewObj = new CInv(TopLeftOrigin, strNewName);
	return pNewObj;
}

void CInv::OutScreen(Graphics &g)
{
	g.DrawPath(m_pPen, m_gPath);
}

void CInv::TransformCObject(Matrix* pMat)
{
	m_gPath->Transform(pMat);
	// need to translate in/out rectangles
	GetBounds();
	Point temppoint = m_pointTL;
	pMat->TransformPoints(&temppoint);
	m_pointTopLeft.x = temppoint.X;
	m_pointTopLeft.y = temppoint.Y;
	m_pointTL.X = temppoint.X;
	m_pointTL.Y = temppoint.Y;

	temppoint.X = m_Connection.m_rectIns[0].left;
	temppoint.Y = m_Connection.m_rectIns[0].top;
	pMat->TransformPoints(&temppoint);
	m_Connection.m_rectIns[0].MoveToXY(temppoint.X,temppoint.Y);

	if(m_Connection.m_pObjectIn[0] && m_Connection.m_pObjectIn[0]->m_nObjType == 4){	// wire
		m_Connection.m_pObjectIn[0]->DisconnectCObject(this);
		DisconnectCObject(m_Connection.m_pObjectIn[0]);
	}


	temppoint.X = m_Connection.m_rectOuts[0].left;
	temppoint.Y = m_Connection.m_rectOuts[0].top;
	pMat->TransformPoints(&temppoint);
	m_Connection.m_rectOuts[0].MoveToXY(temppoint.X,temppoint.Y);

	if(m_Connection.m_pObjectOut[0] && m_Connection.m_pObjectOut[0]->m_nObjType == 4){	// wire
		m_Connection.m_pObjectOut[0]->DisconnectCObject(this);
		DisconnectCObject(m_Connection.m_pObjectOut[0]);
	}
}

Rect* CInv::GetBounds()
{
	int nPntCount = (int)m_gPath->GetPointCount();
	Point *pnts = new Point[nPntCount];
	m_gPath->GetPathPoints(pnts, nPntCount);
	int nXmin, nXmax, nYmin, nYmax;
	nXmax = nXmin = pnts[0].X;
	nYmax = nYmin = pnts[0].Y;
	for(int i=1; i<nPntCount; i++){
		if(pnts[i].X < nXmin)
			nXmin = pnts[i].X;
		if(pnts[i].Y < nYmin)
			nYmin = pnts[i].Y;
		if(pnts[i].X > nXmax)
			nXmax = pnts[i].X;
		if(pnts[i].Y > nYmax)
			nYmax = pnts[i].Y;
	}
	SAFE_DELETE_ARRAY(pnts);
	m_rectBounding.X = nXmin+10;
	m_rectBounding.Y = nYmin;
	m_rectBounding.Width = nXmax-nXmin-10;
	m_rectBounding.Height = nYmax-nYmin;
	return &m_rectBounding;
}

void CInv::OutXml(stringstream &ss)
{
    //<TYPE>Gate</TYPE>
    //<NAME>AndGate0</NAME>
    //<ORIGIN>AND</ORIGIN>
    //<POSITION tlx1="50" tly1="50"></POSITION>
    //<CONNECTIONS>
    //  <INCONNECTIONS nCount ="2">
    //    <IN Name ="InTag0">in</IN>
    //    <IN Name ="InTag1">in</IN>
    //  </INCONNECTIONS>

    //  <OUTCONNECTIONS nCount ="1">
    //    <OUT Name="Wire0">out</OUT>
    //  </OUTCONNECTIONS>
    //</CONNECTIONS>

	ss << "<TYPE>Invertor</TYPE>\n";
	ss << "<NAME>" << (CStringA)m_strUniqueName << "</NAME>\n";
	ss << "<ORIGIN>" << m_strOrigin << "</ORIGIN>\n";
	ss << "<POSITION tlx1 = '" <<  m_pointTopLeft.x << "'" << " tly1 = '" << m_pointTopLeft.y << "'" << "></POSITION>\n";
	ss << "<CONNECTIONS>\n";
	ss << "<INCONNECTIONS nCount=\"" << m_nIn << "\">" << endl;
	for(int i=0; i<m_nIn; i++){
		ss << "<IN Name=\"" << this->m_Connection.m_pObjectIn[i]->m_strUniqueName << "\">in</IN>" << endl;
	}
	ss << "</INCONNECTIONS>" << endl;

	ss << "<OUTCONNECTIONS nCount=\"" << m_nOut << "\">" << endl;
	for(int i=0; i<m_nOut; i++){
		ss << "<OUT Name=\"" << this->m_Connection.m_pObjectOut[i]->m_strUniqueName << "\">out</IN>" << endl;
	}
	ss << "</OUTCONNECTIONS>" << endl;
	ss << "</CONNECTIONS>\n";

}

void CInv::SetConnection(bool bIn, int nPos, CCommonObject* pConnectTo)
{
	if(bIn){
		ASSERT(nPos < m_nIn);
		m_Connection.m_pObjectIn[nPos] = pConnectTo;
	}
	else{
		ASSERT(nPos < m_nOut);
		m_Connection.m_pObjectOut[nPos] = pConnectTo;
	}
}

void CInv::DisconnectCObject(CCommonObject *pObject)
{
	if(m_Connection.m_pObjectIn[0] == pObject){
		m_Connection.m_pObjectIn[0] = NULL;
	}
	if(m_Connection.m_pObjectOut[0] == pObject){
		m_Connection.m_pObjectOut[0] = NULL;
	}
}

void CInv::Disconnect()
{
	if(m_Connection.m_pObjectIn[0]){
		m_Connection.m_pObjectIn[0]->DisconnectCObject(this);
	}
	if(m_Connection.m_pObjectOut[0]){
		m_Connection.m_pObjectOut[0]->DisconnectCObject(this);
	}
}

void CInv::CreateGPath()
{
	SAFE_DELETE(m_gPath);

	m_gPath = new GraphicsPath();
	m_gPath->AddLine(0,0, -4, 0);
	m_gPath->CloseAllFigures();
	m_gPath->AddArc(-10, -3, 6, 6, 0, 360);
	m_gPath->CloseAllFigures();
	m_gPath->AddLine(-10,0, -26,-10);
	m_gPath->AddLine(-26,-10, -26,0);
	m_gPath->AddLine(-26,0, -30,0);
	m_gPath->AddLine(-30,0, -26,0);
	m_gPath->AddLine(-26,0, -26,10);
	m_gPath->AddLine(-26,10, -10,0);
	m_gPath->CloseAllFigures();
}