#include "stdafx.h"
#include "Teleso.h"


Teleso::Teleso(double a, double b, double c)
{
	data = new Bod[8];
	double A = -a/2;
	double B = b/2;
	double C = -c/2;
	for (int i=0;i<8;i++)
	{
		data[i].x=A;
		data[i].y=B;
		data[i].z=C;
		if(i!=0)
			data[i].spoj = new bool[i];
		else
			data[i].spoj = nullptr;
		for (int k=0;k<i;k++)
			data[i].spoj[k]=false;
		A = -A;
		if (A<0) B=-B;
		if ((A<0)&&(B>0)) C=-C;	
	}
	this->count = 8;
	this->InitZobr();
}

Teleso::~Teleso()
{
	if (count>1)
		for (int i=1;i<count;i++)
			delete(data[i].spoj);
	delete(data);
}

void Teleso::Add(double X, double Y, double Z)
{
	Bod novy;
	novy.x = X; 
	novy.y = Y;
	novy.z = Z;
	novy.ZobrX=0;
	novy.ZobrY=0;
	if (count>0)
	{
		novy.spoj = new bool[count];
		for (int i=0;i<count;i++)
			novy.spoj[i] = false;
		Bod* Q = new Bod[count+1];
		for (int i= 0; i<count;i++)
			Q[i]=data[i];
		Q[count]=novy;
		delete(data);
		data = Q;
	}
	else 
	{
		novy.spoj = nullptr;
		data = new Bod;
		data[0]= novy;
	}
	count++;
}

void Teleso::Remove(int N)
{
	
	if (count==1)
	{
		delete(data);
		data = nullptr;
		count = 0;
		return;
	}
	
	Bod *Q = new Bod[count-1];
	for (int i = 0;i<count;i++)
	{
		if (i<N)
			Q[i]=data[i];
		if (i==N)
			delete(data[i].spoj);
		if (i>N)
		{
			Q[i-1]=data[i];
			bool *QQ = new bool[i-1];
			for (int k=0;k<i;k++)
			{
				if (k<N)
					QQ[k]=Q[i-1].spoj[k];
				if (k>N)
					QQ[k-1]=Q[i-1].spoj[k];

			}
			delete(Q[i-1].spoj);
			Q[i-1].spoj = QQ;
		}
	}
	delete(data);
	data = Q;
	count--;
}

void Teleso::operator= (Teleso &A)
{
	if (this->data == A.data) return;
	if (this->data!=nullptr)
	{
		for(int i=1;i<this->count;i++)
			delete( data[i].spoj);
		delete(data);
	}
	data = new Bod[A.count];
	for (int i=0;i<A.count;i++)
	{
		this->data[i]=A.data[i];
		if (i==0)
			this->data[i].spoj = nullptr;
		else
			this->data[i].spoj = new bool[i];
		for (int k=0;k<i;k++)
		{
			this->data[i].spoj[k]=A.data[i].spoj[k];
		}
	}
	this->count=A.count;
	return;
}

void Teleso::InitZobr()
{
	for (int i=0;i<count;i++)
	{
		data[i].ZobrX=0;
		data[i].ZobrY=0;
	}
}

void Teleso::Connect(int Point1,int Point2) 
{
	if (Point1>Point2)
		data[Point1].spoj[Point2]=true;
	if (Point2>Point1)
		data[Point2].spoj[Point1]=true;
}

void Teleso::Disconnect(int Point1,int Point2)
{
	if (Point1>Point2)
		data[Point1].spoj[Point2]=false;
	if (Point2>Point1)
		data[Point2].spoj[Point1]=false; 
}

void Teleso::Save(String^ path)
{
	XmlTextWriter ^s = gcnew XmlTextWriter(path, System::Text::Encoding::UTF8);
	s->Formatting = Formatting::Indented;
	s->WriteStartDocument();
	s->WriteStartElement("Teleso");
	for (int i=0;i<this->count;i++)
	{
		s->WriteStartElement("Bod");

		s->WriteStartElement("X");
		s->WriteString(data[i].x.ToString());
		s->WriteEndElement();

		s->WriteStartElement("Y");
		s->WriteString(data[i].y.ToString());
		s->WriteEndElement();

		s->WriteStartElement("Z");
		s->WriteString(data[i].z.ToString());
		s->WriteEndElement();

		s->WriteStartElement("ImageX");
		s->WriteString(data[i].ZobrX.ToString());
		s->WriteEndElement();

		s->WriteStartElement("ImageY");
		s->WriteString(data[i].ZobrY.ToString());
		s->WriteEndElement();

		s->WriteStartElement("Spojeni");
		for (int k=0;k<i;k++)
		{
			s->WriteStartElement("Bod");
			s->WriteString(data[i].spoj[k].ToString());
			s->WriteEndElement();
		}
		s->WriteEndElement();

		s->WriteEndElement();
	}
	s->WriteEndElement();
	s->WriteEndDocument();
	s->Flush();
	s->Close();
}

void Teleso::Load(String^ path)
{
	XmlTextReader^ r = gcnew XmlTextReader(path);
	r->WhitespaceHandling = WhitespaceHandling::None;
	Teleso Nove = Teleso();
	bool Jednou = true;
	bool x,y,z,q,spojeni;
	try 
	{
		while(Jednou&&r->Read())
			if (r->NodeType==XmlNodeType::Element&&r->Name=="Teleso")
					while(Jednou&&r->Read())		//čtě uvnitř tělesa
					{
						if (r->NodeType==XmlNodeType::EndElement&&r->Name=="Teleso")
						{
							Jednou = false;
							Bod* W = data;
							int A = count;
							this->count = Nove.count;
							this->data = Nove.data;
							Nove.data = W; 
							Nove.count = A;
						}
						if (r->NodeType==XmlNodeType::Element&&r->Name == "Bod")
						{
							x= false;
							y= false;
							z= false;
							q = true;
							spojeni = false;
							Bod Q;
							Q.ZobrX = 0;
							Q.ZobrY = 0;
							Q.spoj = nullptr;
							while(q&&r->Read())
							{	
								if (r->NodeType==XmlNodeType::Element&&r->Name=="X")
								{	
									x = true;
									r->Read();
									Q.x = Convert::ToDouble(r->Value);
									r->Read();
								}
								if (r->NodeType==XmlNodeType::Element&&r->Name == "Y")
								{
									y = true;
									r->Read();
									Q.y = Convert::ToDouble(r->Value);
									r->Read();
								}
								if (r->NodeType==XmlNodeType::Element&&r->Name == "Z")
								{
									z = true;
									r->Read();
									Q.z = Convert::ToDouble(r->Value);
									r->Read();
								}
								if (r->NodeType==XmlNodeType::Element&&r->Name == "ImageX")
								{
									r->Read();
									Q.ZobrX = Convert::ToDouble(r->Value);
									r->Read();
								}
								if (r->NodeType==XmlNodeType::Element&&r->Name == "ImageY")
								{
									r->Read();
									Q.ZobrY = Convert::ToDouble(r->Value);
									r->Read();
								}
								if (r->NodeType==XmlNodeType::Element&&r->Name == "Spojeni")
								{
									int i = 0;
									bool p = true;
									bool *pole = new bool[Nove.count]; 
									while(p&&r->Read())
									{
										if (r->NodeType==XmlNodeType::EndElement&&r->Name == "Bod")
										{
											p = false;
											Q.spoj = pole;
											spojeni = true;
										}
										if (r->NodeType==XmlNodeType::EndElement&&r->Name == "Spojeni")
										{
											p = false;
											if (i==Nove.count)
											{
												spojeni = true;
												Q.spoj = pole;
											}
											else
												delete(pole);
										}
										if (r->NodeType==XmlNodeType::Element&&r->Name == "Bod")
										{
											r->Read();
											pole[i++] = Convert::ToBoolean(r->Value);
											r->Read();
										}
									}
								}
								if (r->NodeType==XmlNodeType::EndElement&&r->Name == "Bod")
								{
									q = false;
									if (spojeni)
										{if (x&&y&&z) Nove.Add(Q);}
									else
										{if (x&&y&&z) Nove.Add(Q.x,Q.y,Q.z);}
								}
							}
						}
						
					}

	}
	finally
	{
		if ( r != nullptr )
            r->Close();
	}

}	

void Teleso::Add(Bod x)
{
	if (count>0)
	{
		Bod* Q = new Bod[count+1];
		for (int i= 0; i<count;i++)
			Q[i]=data[i];
		Q[count]=x;
		delete(data);
		data = Q;
	}
	else 
	{
		data = new Bod;
		data[0]= x;
	}
	count++;
}
