#include "Printer.h"
#include "Circuit.h"
#include <direct.h>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>

#define OUTPUT_SPC 50 


Printer::Printer(Circuit* circuit)
{
	this->circuit = circuit;
}

Printer::~Printer(void)
{
}

void Printer::printXml(string fileName){
	fstream ps,fs;
	Piece* p;
	Node* n;
	Node* nn;
	Connection* c;
	Connection cc;
	Point* pnt;
	int ipin;
	vector<Node*> inNodes;
	vector<Node*> outNodes;
	vector<Connection*> inCnnts;
	vector<Connection*> outCnnts;
	string t1 = "\t";
	string t2 = t1 + "\t";
	string t3 = t2 + "\t";
	string t4 = t3 + "\t";
	string t5 = t4 + "\t";
	_mkdir((fileName + "Project").c_str());
	//TODO doplnit originalne mena

	// vytvorenie projektu
	ps.open((fileName + "Project\\" + fileName + ".xml").c_str() , fstream::out);
	ps << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << endl;
	ps << "<Project display=\"" << fileName << "\" filename=\"" << fileName << "\">" << endl;
	ps << "<TYPE>Project</TYPE>" << endl;
	ps << "<NAME>" << fileName << "</NAME>" << endl;
	ps << t1 << "<CONTENT>" << endl;
	ps << t2 << "<ELEM type=\"1\">" << endl;
	ps << t3 << "<DISPLAY>" << fileName << "Scheme</DISPLAY>" << endl;
	ps << t3 << "<ORIGIN inProject=\"1\">" << fileName << "Scheme</ORIGIN>" << endl;
	ps << t2 << "</ELEM>" << endl;
	ps << t1 << "</CONTENT>" << endl;
	ps << "</Project>" << endl;

	// vytvorenie schemy
	_mkdir((fileName + "Project\\Content").c_str());
	//char* fileNameXml = (char *)fileName + ".xml";
	//cout << "File name" << fileNameXml << endl;
	fs.open((fileName + "Project\\Content\\" + fileName + "Scheme.xml").c_str(), fstream::out);
	fs << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << endl;
	fs << "<SCHEME filename=\"" << fileName << "Scheme.xml\">" << endl;
	fs << t1 << "<TYPE>Scheme</TYPE>" << endl;
	fs << t1 << "<NAME>" << fileName << "Scheme</NAME>" << endl;
	fs << t1 << "<CONTENT>" << endl;
	//vytvorenie prvkov
	for(unsigned int ip = 0; ip < circuit->getPieces()->size(); ip++){
		p = circuit->getPieces()->at(ip);
		inNodes.clear();
		outNodes.clear();
		inCnnts.clear();
		outCnnts.clear();
		for(unsigned int in = 0; in < circuit->nodes.size(); in++){
			n = circuit->nodes.at(in);
			if(n->right.compare(p->rule->getName()) == 0){
				inNodes.push_back(n);
			}
			if(n->left.compare(p->rule->getName()) == 0){
				outNodes.push_back(n);
			}
		}
		for(unsigned int ic = 0; ic < circuit->connections.size(); ic++){
			c = &(circuit->connections.at(ic));
			for(unsigned int in = 0; in < inNodes.size(); in++){
				nn = c->end;
				if(inNodes.at(in)->comp(nn)){
					inCnnts.push_back(c);
					break;
				}
			}
			for(unsigned int in = 0; in < outNodes.size(); in++){
				nn = c->start;
				if(outNodes.at(in)->comp(nn)){
					outCnnts.push_back(c);
					break;
				}
			}
		}
		fs << t2 << "<ELEM type=\"3\">" << endl;
		fs << t3 << "<DISPLAY>" << p->rule->getName() << "</DISPLAY>" << endl;
		fs << t3 << "<ORIGIN inProject=\"0\">" << p->rule->getType() << "</ORIGIN>" << endl;
		fs << t3 << "<NAME>" << p->rule->getName() << "</NAME>" << endl;
		fs << t3 << "<POSITION tlx1=\"" << p->x << "\" tly1=\"" << p->y <<"\"/>" << endl;
		fs << t3 << "<CONNECTIONS>" << endl;
		fs << t4 << "<INCONNECTIONS nCount=\"" << inCnnts.size() << "\">" << endl;
		for(unsigned int ic = 0; ic < inCnnts.size(); ic++){
			c = inCnnts.at(ic);
			fs << t5 << "<IN Name=\"" << c->name << "\">" << ic << "</IN>" << endl;
		}
		fs << t4 << "</INCONNECTIONS>" << endl;
		fs << t4 << "<OUTCONNECTIONS nCount=\"" << 
			(circuit->isOutputIncluded(p->rule->getName()) ? 
			outCnnts.size() + 1: outCnnts.size())
			<< "\">" << endl;
		for(unsigned int ic = 0; ic < outCnnts.size(); ic++){
			c = outCnnts.at(ic);
			fs << t5 << "<OUT Name=\"" << c->name << "\">" << ic << "</OUT>" << endl;
		}
		if(circuit->isOutputIncluded(p->rule->getName())){
			fs << t5 << "<OUT Name=\"Wire_" << p->rule->getName() << "_OUT\">" 
				<< 0 << "</OUT>" << endl;
		}
		fs << t4 << "</OUTCONNECTIONS>" << endl;
		fs << t3 << "</CONNECTIONS>" << endl;
		fs << t2 << "</ELEM>" << endl;
		//Pridanie prvkov typu output
		if(circuit->isOutputIncluded(p->rule->getName())){
			fs << t2 << "<ELEM type=\"3\">" << endl;
			fs << t3 << "<DISPLAY>" << p->rule->getName() << "_OUT</DISPLAY>" << endl;
			fs << t3 << "<ORIGIN inProject=\"0\">OUTPUT</ORIGIN>" << endl;
			fs << t3 << "<NAME>" << p->rule->getName() << "_OUT</NAME>" << endl;
			fs << t3 << "<POSITION tlx1=\"" << p->x + p->width + OUTPUT_SPC 
				<< "\" tly1=\"" << p->y + p->outputY->at(0) <<"\"/>" << endl;
			fs << t3 << "<CONNECTIONS>" << endl;
			fs << t4 << "<INCONNECTIONS nCount=\"" << 1 << "\">" << endl;
			fs << t5 << "<IN Name=\"Wire_" << p->rule->getName() << "_OUT\">" 
				<< 0 << "</IN>" << endl;
			fs << t4 << "</INCONNECTIONS>" << endl;
			fs << t4 << "<OUTCONNECTIONS nCount=\"" << 0 << "\"/>" << endl;
			fs << t3 << "</CONNECTIONS>" << endl;
			fs << t2 << "</ELEM>" << endl;

			//vytvorenie spoja pre output
			fs << t2 << "<ELEM type=\"4\">" << endl;
			fs << t3 << "<DISPLAY>Wire_" << p->rule->getName() << "_OUT</DISPLAY>" << endl;
			fs << t3 << "<ORIGIN inProject=\"1\">Wire</ORIGIN>" << endl;
			fs << t3 << "<NAME>Wire_" << p->rule->getName() << "_OUT</NAME>" << endl;
			fs << t3 << "<POSITION tlx1=\"0\" tly1=\"0\"/>" << endl;
			fs << t3 << "<ANCHORS nIn=\"1\" nOut=\"1\">" << endl;
			fs << t4 << "<POINT x=\"" << p->x + p->width << "\" y=\"" 
				<< p->y + p->outputY->at(0) <<"\"/>" << endl;
			fs << t4 << "<POINT x=\"" << p->x + p->width + OUTPUT_SPC - 40
				<< "\" y=\"" << p->y + p->outputY->at(0) <<"\"/>" << endl;
			fs << t3 << "</ANCHORS>" << endl;
			fs << t3 << "<CONNECTIONS>" << endl;
			fs << t4 << "<INCONNECTIONS nCount=\"1\">" << endl;
			fs << t5 << "<IN Name=\"" << p->rule->getName() << "\">" << 0 << "</IN>" << endl;
			fs << t4 << "</INCONNECTIONS>" << endl;
			fs << t4 << "<OUTCONNECTIONS nCount=\"" << 1 << "\">" << endl;
			fs << t5 << "<OUT Name=\"" << p->rule->getName() << "_OUT\">" 
				<< 0 << "</OUT>" << endl;
			fs << t4 << "</OUTCONNECTIONS>" << endl;
			fs << t3 << "</CONNECTIONS>" << endl;
			fs << t2 << "</ELEM>" << endl;
		}
	}
	//vypisanie vsetkych spojeni
	for(unsigned int ic = 0; ic < circuit->connections.size(); ic++){
		c = &(circuit->connections.at(ic));
		cc = circuit->connections.at(ic);
		fs << t2 << "<ELEM type=\"4\">" << endl;
		fs << t3 << "<DISPLAY>" << c->name << "</DISPLAY>" << endl;
		fs << t3 << "<ORIGIN inProject=\"1\">Wire</ORIGIN>" << endl;
		fs << t3 << "<NAME>" << c->name << "</NAME>" << endl;
		fs << t3 << "<POSITION tlx1=\"0\" tly1=\"0\"/>" << endl;
		fs << t3 << "<ANCHORS nIn=\"" << c->start->cnnts(c->name) << "\" nOut=\"" << c->end->cnnts(c->name) << "\">" << endl;
		for(unsigned int ipnt = 0; ipnt < c->path.size(); ipnt++){
			pnt = &(c->path.at(ipnt));
			fs << t4 << "<POINT x=\"" << pnt->x << "\" y=\"" << pnt->y <<"\"/>" << endl;
		}
		fs << t3 << "</ANCHORS>" << endl;
		fs << t3 << "<CONNECTIONS>" << endl;
		fs << t4 << "<INCONNECTIONS nCount=\"" << c->start->cnnts(c->name) << "\">" << endl;
		ipin = 0;
		if(!c->start->left.empty() && c->start->left.compare(c->name) != 0){
			fs << t5 << "<IN Name=\"" << c->start->left 
				<< "\">" << ipin << "</IN>" << endl;
			ipin++;
		}
		if(!c->start->right.empty() && c->start->right.compare(c->name) != 0){
			fs << t5 << "<IN Name=\"" << c->start->right 
				<< "\">" << ipin << "</IN>" << endl;
			ipin++;
		}
		if(!c->start->up.empty() && c->start->up.compare(c->name) != 0){
			fs << t5 << "<IN Name=\"" << c->start->up 
				<< "\">" << ipin << "</IN>" << endl;
			ipin++;
		}
		if(!c->start->down.empty() && c->start->down.compare(c->name) != 0){
			fs << t5 << "<IN Name=\"" << c->start->down 
				<< "\">" << ipin << "</IN>" << endl;
			ipin++;
		}
		fs << t4 << "</INCONNECTIONS>" << endl;
		fs << t4 << "<OUTCONNECTIONS nCount=\"" << c->end->cnnts(c->name) << "\">" << endl;
		ipin = 0;
		if(!c->end->left.empty() && c->end->left.compare(c->name) != 0){
			fs << t5 << "<OUT Name=\"" << c->end->left 
				<< "\">" << ipin << "</OUT>" << endl;
			ipin++;
		}
		if(!c->end->right.empty() && c->end->right.compare(c->name) != 0){
			fs << t5 << "<OUT Name=\"" << c->end->right 
				<< "\">" << ipin << "</OUT>" << endl;
			ipin++;
		}
		if(!c->end->up.empty() && c->end->up.compare(c->name) != 0){
			fs << t5 << "<OUT Name=\"" << c->end->up 
				<< "\">" << ipin << "</OUT>" << endl;
			ipin++;
		}
		if(!c->end->down.empty() && c->end->down.compare(c->name) != 0){
			fs << t5 << "<OUT Name=\"" << c->end->down 
				<< "\">" << ipin << "</OUT>" << endl;
			ipin++;
		}
		fs << t4 << "</OUTCONNECTIONS>" << endl;
		fs << t3 << "</CONNECTIONS>" << endl;
		fs << t2 << "</ELEM>" << endl;
	}
	fs << t1 << "</CONTENT>" << endl;
	fs << "</SCHEME>" << endl;
	fs.close();
}
