#include "StdAfx.h"
#include "XmlCreator.h"
#include "CommonObject.h"
#include "Block.h"
#include "INKS.h"
#include "INKSDoc.h"
#include "TreeBar.h"
#include "Tag.h"

CXmlCreator::CXmlCreator()
	: m_pList(NULL), m_pNewBlock(NULL)
{

}

CXmlCreator::~CXmlCreator()
{
}

void CXmlCreator::Reset()
{
	m_pList = NULL;
	m_pNewBlock = NULL;
	ss.clear();
}

stringstream& CXmlCreator::WriteProject(CString strProjectName, CINKSDoc *pProjectDoc)
{
	ss << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n" << endl;
	ss << "<Project display=\""<< (CStringA)strProjectName << "\" filename=\"" << (CStringA)strProjectName << ".xml\">" << endl;
	ss << "<TYPE>Project</TYPE>" << endl;
	ss << "<NAME>" << (CStringA)strProjectName << "</NAME>" << endl;
	ss << "\t<CONTENT>" << endl;
	if(pProjectDoc && pProjectDoc->m_pTreeItem){
		POSITION pos = pProjectDoc->m_pTreeItem->m_slContent.GetHeadPosition();
		CString strName;
		while(pos){
			strName = strName = pProjectDoc->m_pTreeItem->m_slContent.GetNext(pos);
			ss << "\t\t<ELEM type=\"1\">" << endl;
			ss << "\t\t\t<DISPLAY>" << (CStringA)strName << "</DISPLAY>" << endl;
			ss << "\t\t\t<ORIGIN inProject=\"1\">" << (CStringA)strName << "</ORIGIN>" << endl;
			ss << "\t\t</ELEM>" << endl;
		}
	}
	ss << "\t</CONTENT>" << endl;
	ss << "</Project>" << endl;
	return ss;
}

stringstream& CXmlCreator::WriteScheme(CString strSchemeName, CList<CCommonObject*, CCommonObject*> *pList)
{
	ss << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n" << endl;
	ss << "<SCHEME filename=\"" << (CStringA)strSchemeName << ".xml\">" << endl;
	ss << "\t<TYPE>Scheme</TYPE>" << endl;
	ss << "\t<NAME>" << (CStringA)strSchemeName << "</NAME>" << endl;
	ss << "\t\t<CONTENT>" << endl;
	if(pList){
		POSITION pos = pList->GetHeadPosition();
		CCommonObject *pObj = NULL;
		while(pos){
			pObj = pList->GetNext(pos);
			WriteElement(pObj, ss);
			ss << endl;
		}
	}
	ss << "\t\t</CONTENT>" << endl;
	ss << "</SCHEME>" << endl;
	return ss;
}

stringstream& CXmlCreator::WriteBlock(CString strBlockName, CList<CCommonObject*, CCommonObject*> *pList, CBlock *pBlock)
{
	CBlock *pBlockTemp = (CBlock*)pBlock;
	ss << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n" << endl;
	ss << "<GBLOCK>" << endl;
	ss << "<TYPE>Block</TYPE>" << endl;
	ss << "<NAME>" << (CStringA)strBlockName << "</NAME>" << endl << endl;
	ss << "\t<CONTENT>" << endl;
	if(pList){
		POSITION pos = pList->GetHeadPosition();
		CCommonObject *pObj = NULL;
		while(pos){
			pObj = pList->GetNext(pos);
			WriteElement(pObj, ss);
			ss << endl;
		}
	}
	ss << "\t</CONTENT>" << endl;

	if(pBlock)
		pBlock->OutXmlDrawing(ss);
	else{
		WriteBlockDrawing(pList, ss);
	}

	ss << "</GBLOCK>" << endl;
	return ss;
}

void CXmlCreator::WriteBlockDrawing(CList<CCommonObject*, CCommonObject*> *pList, stringstream &ss)
{
	int nIn = 0;
	int nOut = 0;
	int nInWidth = 0;
	int nOutWidth = 0;
	CStringList slIns;
	CStringList slOuts;
	
	CCommonObject *pObj = NULL;
	CTag *pTag = NULL;

	POSITION pos = pList->GetHeadPosition();
	while(pos){
		pObj = pList->GetNext(pos);
		if(pObj->m_nObjType == 5){
			pTag = (CTag*)pObj;
			if(pTag->m_nTagType == 1){
				nIn++;
				slIns.AddTail(pTag->m_strUniqueName);
				if(nInWidth < pObj->m_strUniqueName.GetLength())
					nInWidth = pObj->m_strUniqueName.GetLength();
			}
			else{
				nOut++;
				slOuts.AddTail(pTag->m_strUniqueName);
				if(nOutWidth < pObj->m_strUniqueName.GetLength())
					nOutWidth = pObj->m_strUniqueName.GetLength();
			}
		}
	}
	int nBlockWidth = nInWidth*20 + nOutWidth*20 + 20;
	int nBlockHeigth;
	nIn > nOut ? nBlockHeigth = nIn*20 : nBlockHeigth = nOut*20;
	if(nBlockHeigth < 50)
		nBlockHeigth = 50;


  //<DRAWING>
  //  <BODY nRecords="5">
  //    <LINE x1="0" y1="0" x2="50" y2="0">line</LINE>
  //    <LINE x1="50" y1="0" x2="50" y2="120">line</LINE>
  //    <LINE x1="50" y1="120" x2="0" y2="120">line</LINE>
  //    <LINE x1="0" y1="120" x2="0" y2="0">line</LINE>
  //    <CLOSEFIGURE>closefigure</CLOSEFIGURE>
  //  </BODY>
	int nRecords = 5;
	ss << "\t<DRAWING>" << endl;
	ss << "\t\t<BODY nRecords=\"" << nRecords << "\">" << endl;
	ss << "\t\t\t<LINE x1=\"0\" y1=\"0\" x2=\"" << nBlockWidth << "\" y2=\"0\">line</LINE>" << endl;
	ss << "\t\t\t<LINE x1=\"" << nBlockWidth << "\" y1=\"0\" x2=\"" << nBlockWidth << "\" y2=\"" << nBlockHeigth << "\">line</LINE>" << endl;
	ss << "\t\t\t<LINE x1=\""<< nBlockWidth << "\" y1=\"" << nBlockHeigth << "\" x2=\"0\" y2=\"" << nBlockHeigth << "\">line</LINE>" << endl;
	ss << "\t\t\t<LINE x1=\"0\" y1=\"" << nBlockHeigth << "\" x2=\"0\" y2=\"0\">line</LINE>" << endl;
	ss << "\t\t\t<CLOSEFIGURE>closefigure</CLOSEFIGURE>" << endl;
	ss << endl;
	ss << "\t\t</BODY>" << endl << endl;
  //  <OUTPUTS nOut="2" nRecords="6">
  //    <LINE x1="50" y1="10" x2="70" y2="10">line</LINE>
  //    <CLOSEFIGURE>closefigure</CLOSEFIGURE>
  //    <LINE x1="50" y1="30" x2="70" y2="30">line</LINE>
  //    <CLOSEFIGURE>closefigure</CLOSEFIGURE>
  //    <TEXT pos="0" text="out0">text</TEXT>
  //    <TEXT pos="1" text="out1">text</TEXT>
  //  </OUTPUTS>
	pos = slOuts.GetHeadPosition();
	nRecords = nOut*3;
	ss << "\t\t<OUTPUTS nOut=\"" << nOut << "\" nRecords =\"" << nRecords << "\">" << endl;
	for(int i=0; i<nOut; i++){
		ss << "\t\t\t<LINE x1=\"" << nBlockWidth << "\" y1=\"" << i*20+20 << "\" x2=\"" << nBlockWidth+20 << "\" y2=\"" << i*20+20 << "\">line</LINE>" << endl;
		ss << "\t\t\t<CLOSEFIGURE>closefigure</CLOSEFIGURE>" << endl;
		ss << "\t\t\t<TEXT pos=\"" << i << "\" text=\"" << (CStringA)slOuts.GetNext(pos) << "\">text</TEXT>" << endl;
	}//(CStringA)m_strOutTags[i]
	ss << "\t\t</OUTPUTS>" << endl << endl;

  //  <INPUTS nIn="3" nRecords="9">
  //    <LINE x1="-20" y1="10" x2="0" y2="10">line</LINE>
  //    <CLOSEFIGURE>closefigure</CLOSEFIGURE>
  //    <LINE x1="-20" y1="30" x2="0" y2="30">line</LINE>
  //    <CLOSEFIGURE>closefigure</CLOSEFIGURE>
  //    <LINE x1="-20" y1="50" x2="0" y2="50">line</LINE>
  //    <CLOSEFIGURE>closefigure</CLOSEFIGURE>
  //    <TEXT pos="0" text="in0">text</TEXT>
  //    <TEXT pos="1" text="in1">text</TEXT>
  //    <TEXT pos="2" text="in2">text</TEXT>
  //  </INPUTS>
	pos = slIns.GetHeadPosition();
	nRecords = nIn*3;
	ss << "\t\t<INPUTS nIn=\"" << nIn << "\" nRecords =\"" << nRecords << "\">" << endl;
	for(int i=0; i<nIn; i++){
		ss << "\t\t\t<LINE x1=\"-20\" y1=\"" << i*20+20 << "\" x2=\"0\" y2=\"" << i*20+20 << "\">line</LINE>" << endl;
		ss << "\t\t\t<CLOSEFIGURE>closefigure</CLOSEFIGURE>" << endl;
		ss << "\t\t\t<TEXT pos=\"" << i << "\" text=\"" << (CStringA)slIns.GetNext(pos) << "\">text</TEXT>" << endl;
	}
	ss << "\t\t</INPUTS>" << endl;
	ss << "\t</DRAWING>" << endl;

	ss << "\t\t<COBJINFO>" << endl;
	ss << "\t\t<INPUTRECT nRecords=\"" << nIn << "\">" << endl;
	for(int i=0; i<nIn; i++){
		ss << "\t\t\t<INPUT x1=\"-20\" y1=\"" << i*20+20 << "\" inv=\"0\">" << i << "</INPUT>" << endl;
	}
	ss << "\t\t</INPUTRECT>" << endl << endl;
	ss << "\t\t<OUTPUTRECT nRecords=\"" << nOut << "\">" << endl;
	for(int i=0; i<nOut; i++){
		ss << "\t\t\t<OUTPUT x1=\"" << nBlockWidth+20 << "\" y1=\"" << i*20+20 << "\" inv=\"0\">" << i << "</OUTPUT>" << endl;
	}
	ss << "\t\t</OUTPUTRECT>" << endl << endl;
	ss << "\t\t</COBJINFO>" << endl;
  //</DRAWING>
}

void CXmlCreator::WriteElement(CCommonObject *pObj, stringstream &ss, int nLevel)
{
	bool bInProject = false;;
	if(theApp.m_pOpenedProjectDoc && theApp.m_pOpenedProjectDoc->m_pElementCont && theApp.m_pOpenedProjectDoc->m_pElementCont->ContainsElement((CString)pObj->m_strOrigin)){
		bInProject = true;
	}
	if(pObj->m_nObjType == 4){ // this is a wire, it has its own outXml method
		pObj->OutXml(ss);
	}
	else{
		CStringA strLevel;
		for(int i=0; i<nLevel; i++){
			strLevel.Append("\t");
		}
		int nFileInPro;
		//pObj->m_bFileInProject ? nFileInPro = 1 : nFileInPro = 0;
		if(pObj->m_bFileInProject)
			nFileInPro = 1;
		else nFileInPro = 0;
		CStringA strLevel1 = strLevel + "\t";
		CStringA strLevel2 = strLevel1 + "\t";
		CStringA strLevel3 = strLevel2 + "\t";

		ss << strLevel << "<ELEM type=\"" << pObj->m_nObjType << "\">" << endl;
		ss << strLevel1 << "<DISPLAY>" << (CStringA)pObj->m_strUniqueName << "</DISPLAY>" << endl;
		ss << strLevel1 << "<ORIGIN inProject=\"" << nFileInPro << "\">" << pObj->m_strOrigin << "</ORIGIN>" << endl;
		ss << strLevel1 << "<NAME>" << (CStringA)pObj->m_strUniqueName << "</NAME>" << endl;
		ss << strLevel1 << "<POSITION tlx1=\"" << pObj->m_pointTopLeft.x << "\" tly1=\"" << pObj->m_pointTopLeft.y << "\"></POSITION>" << endl;
		ss << strLevel1 << "<CONNECTIONS>" << endl;

		int nIn = 0;
		for(int i=0; i<pObj->m_nIn; i++){
			if(pObj->m_Connection.m_pObjectIn[i])
				nIn++;
		}
		ss << strLevel2 << "<INCONNECTIONS nCount=\"" << nIn << "\">" << endl;
		for(int i=0; i<pObj->m_nIn; i++){
			if(pObj->m_Connection.m_pObjectIn[i])
				ss << strLevel3 << "<IN Name=\"" << (CStringA)pObj->m_Connection.m_pObjectIn[i]->m_strUniqueName << "\">" << i << "</IN>" << endl;
		}
		ss << strLevel2 << "</INCONNECTIONS>" << endl;

		int nOut = 0;
		for(int i=0; i<pObj->m_nOut; i++){
			if(pObj->m_Connection.m_pObjectOut[i])
				nOut++;
		}

		ss << strLevel2 << "<OUTCONNECTIONS nCount=\"" << nOut << "\">" << endl;
		for(int i=0; i<pObj->m_nOut; i++){
			if(pObj->m_Connection.m_pObjectOut[i])
				ss << strLevel3 << "<OUT Name=\"" << (CStringA)pObj->m_Connection.m_pObjectOut[i]->m_strUniqueName << "\">" << i <<  "</OUT>" << endl;
		}
		ss << strLevel2 << "</OUTCONNECTIONS>" << endl;

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