#include <stdio.h>
#include <iostream.h>
#include "knihovna.h"




//-----------------------------------------------------dijkstra

int PathFind(TMap *map,int start,int finish,int route[],int *nodesOnRoute,int *routeLenght)				//funkce Path Finder
{  
int edge[COUNT][COUNT];													//vytvori pole hran
int nodeCount=map->count;
int counter=0;

 														//inicializace poctu hran

for(int i=0;i<COUNT;i++)                //vymazani trasy
        {
        route[i]=0;
        }

//---------vycisteni hran.... Mozna neni potreba
for(int i=0;i<COUNT;i++)
        for(int j=0;j<COUNT;j++)
                edge[i][j]=0;



start--;                //to je tu kvuli posunu indexace o 1
finish--;

if(nodeCount<=0)return(-1);												//kontrola spravneho nacteni udaju
if(nodeCount>COUNT)return(-10);

for(int i=0;i<nodeCount;i++)											//nacteni hran ze souboru
	{for(int j=0;j<nodeCount;j++)
		{
                edge[i][j]=map->edge[i][j];
		};
	};

//--------------------------------inicializace
																		//vzdalenost neznamych vrcholu je nastavena na 32000 (predpokladam ze delky hran budou radove mensi)
TNodePF node[COUNT];                    //vytvori pole vrcholu
for(int i=0;i<COUNT;i++)
		{
		node[i].SetDistance(32000);
		node[i].SetAncestor(32000);
		node[i].Unfix();
		};



node[start].SetDistance(0);											//vzdalenost prvniho prvku od pocatku je logicky 0
node[start].SetAncestor(32001);		 //hodnota 32001 znaci ze prvek nema predchudce

while(!node[finish].IsFixed())		 //ukonci beh algoritmu v momente kdy je cilovy vrchol urcen jako trvaly
{
int actual=0;
int min=32000;

if(counter>COUNT)return(-11);           //ochrana proti zacykleni
counter++;

//int closest=0;
for(int i=0;i<nodeCount;i++)				     //cyklus vybira vrchol pro dalsi krok
		{
		if(!node[i].IsFixed())
			{
			if(node[i].GetDistance()<min)           
				{
				min=node[i].GetDistance();
				actual=i;		      //oznacuje prvek se kterym se bude v dalsim kroku pracovat
				};
			};
		};
node[actual].Fix();													//po kazdem cyklu je jeden prvek oznacen jako pevny

for(int i=0;i<nodeCount;i++)											//nastavi docasne vzdalenosti sousedu od pocatku
		{
		if((edge[actual][i]<32000)&&(edge[actual][i]>0))			//prvni podminka zrejme neni nutna, ale clovek nikdy nevi :)
				{
				if((node[actual].GetDistance()+edge[actual][i])<node[i].GetDistance())			//porovnava puvodni a novou vzdalenost
						{node[i].SetAncestor(actual);					       	//pokud je nova kratsi, prepise predka
						node[i].SetDistance(node[actual].GetDistance()+edge[actual][i]);	//a vzdalenost
						}
				}

		}
};


//-------------------------tato cast zajistuje vystupy z funkce
int tmp=finish;
int tmp2=1;

while(node[tmp].GetAncestor()!=32001)			//konkretne tvorba trasy
	{
	tmp=node[tmp].GetAncestor();
	route[tmp2]=tmp;
	tmp2++;
	}
route[0]=finish;

for(int i=0;i<=tmp2/2-1;i++)							//obraceni posloupnosti vrcholu
	{
	int tmp=route[i];
	route[i]=route[tmp2-i-1];
	route[tmp2-i-1]=tmp;
	}

*nodesOnRoute=tmp2;

//-----------------------------kontrolni vypis cesty do souboru
FILE *f;
f=fopen("xCesta.txt","wt");
								//pocet vrcholu na trase
*routeLenght=node[finish].GetDistance();		//a celkova delka trasy
fprintf(f,"Uzlu na trase je: %d\nDelka trasy je: %d\nCesta vede pres: \n",tmp2,node[finish].GetDistance());
for(int i=0;i<tmp2;i++)
        fprintf(f,"     %s		ID:%d\n",map->node[route[i]].name,map->node[route[i]].ID);
fclose(f);


return (0);


};

int Preklad(TMap *Mapa,int cesta[],int prelCesta[], int pocet)     //preklad cesty na odbocky
{
int IndexVjezdu=4;
int IndexVyjezdu=4;

for(int i=0;i<COUNT;i++)                //vymazani trasy
        {
        prelCesta[i]=3;
        }

for(int i=1;i<pocet-1;i++)
        {
        for(int j=0;j<4;j++)     //hleda z kama vjede do krizovatky
                {
                if(Mapa->node[cesta[i]].neighbour[j]==Mapa->node[cesta[i-1]].ID)
                        {
                        IndexVjezdu=j;
                        }
                }

        for(int j=0;j<4;j++)     //hleda z kama vyjede z krizovatky
                {
                if(Mapa->node[cesta[i]].neighbour[j]==Mapa->node[cesta[i+1]].ID)
                        {
                        IndexVyjezdu=j;
                        }
                }

        int smer=IndexVyjezdu-IndexVjezdu;
        switch(smer)
                {
                case -3:
                prelCesta[i]=1;    //vpravo
                break;
                case -2:
                prelCesta[i]=0;    //rovne
                break;
                case -1:
                prelCesta[i]=2;    //vlevo
                break;
                case 1:
                prelCesta[i]=1;    //vpravo
                break;
                case 2:
                prelCesta[i]=0;    //rovne
                break;
                case 3:
                prelCesta[i]=2;    //vlevo
                break;
                default:
                return (-smer);       //chyba
                break;
                }

        };

prelCesta[pocet-1]=3;     //zastaveni v cili

FILE *f;
f=fopen("xy.txt","wt");
fprintf(f,"Preklad cesty:\n");

for(int i=1;i<pocet;i++)
        switch(prelCesta[i])
                {
                case 0:
                fprintf(f,"%30s   %s\n",Mapa->node[cesta[i]].name,"rovne");
                break;
                case 1:
                fprintf(f,"%30s   %s\n",Mapa->node[cesta[i]].name,"vpravo");
                break;
                case 2:
                fprintf(f,"%30s   %s\n",Mapa->node[cesta[i]].name,"vlevo");
                break;
                case 3:
                fprintf(f,"%30s   %s\n",Mapa->node[cesta[i]].name,"zastavit");
                break;
                }
fclose(f);


return (0);
}





//----------------------------fce pro praci se souborem mapy

int Save(char *path,TMap *map)
{
TNode x;
FILE *f;
if((map->count<0)||(map->count>100))return (-12);         //spatny pocet krizovatek
f=fopen(path,"wt");            //otevreni textoveho souboru pro zapis
if(f==NULL)return (-10);       //nelze otevrit soubor
fprintf(f,"72513	%d\n",map->count);           //tu by mohla byt chyba s tabulatorem

for(int i=0;i<map->count;i++)			     //ulozeni matice								//nacteni hran ze souboru
	{for(int j=0;j<map->count;j++)
		{fprintf(f,"%d	",map->edge[i][j]);
		};
         fprintf(f,"\n");
	};

fprintf(f,"\n\n");

for(int i=0;i<map->count;i++)                          //ulozeni krizovatek
{
fprintf(f,"%d	%d	%s	%d	%d	%d	%d	%d\n",map->node[i].ID,map->node[i].order,&map->node[i].name,map->node[i].neighbour[0],map->node[i].neighbour[1],map->node[i].neighbour[2],map->node[i].neighbour[3],map->node[i].terminal);
};


fclose(f);
return 0;
};



int Read(char *path,TMap *map)
{
int MYID=0;
int count=0;
FILE *f;
f=fopen(path,"rt");            //otevreni textoveho souboru pro cteni
if(f==NULL)return (-10);       //nelze otevrit soubor
fscanf(f,"%d	%d\n",&MYID,&count);
if(MYID!=72513)return (-11);     //nacten spatny soubor
for(int i=0;i<count;i++)			     //nacteni matice								//nacteni hran ze souboru
	{for(int j=0;j<count;j++)
	       	{fscanf(f,"%d	",&map->edge[i][j]);
	       	};
	};
map->count=count;
fscanf(f,"\n\n");



for(int i=0;i<map->count;i++)                          //nacteni krizovatek
{
fscanf(f,"%d	%d	%s	%d	%d	%d	%d	%d\n",
&map->node[i].ID,&map->node[i].order,&map->node[i].name,&map->node[i].neighbour[0],
&map->node[i].neighbour[1],&map->node[i].neighbour[2],&map->node[i].neighbour[3],&map->node[i].terminal);
};
fclose(f);
return 0;
};




//----------------------------fce pro praci s Nodama

int GetOrder(TMap *map,int ID)   //vrati poradi krizovatky podle ID !!! Nezapomen odecist 1
{
int i=0;
while(map->node[i].ID!=ID)
        if(i<map->count)i++;
        else return (0);
return (map->node[i].order);
}


int GetOrder(TMap *map,char *name)
{
int i=0;
while(strcmp(map->node[i].name,name))
        if(i<map->count)i++;
        else return (0);
return (map->node[i].order);
}

void DeleteNode(TMap *Mapa ,int NodeOrder)
        {
        for(int i=0;i<Mapa->count;i++)                                 //vyhodi xty sloupec matice
                {
                for(int j=NodeOrder;j<Mapa->count-1;j++)
                        {
                        Mapa->edge[i][j]=Mapa->edge[i][j+1];
                        }

                };
        for(int i=NodeOrder;i<Mapa->count;i++)                                   //vyhodi xty radek matice
                {
                for(int j=0;j<Mapa->count-1;j++)
                        {
                        Mapa->edge[i][j]=Mapa->edge[i+1][j];
                        }

                };
        for(int i=NodeOrder;i<Mapa->count-1;i++)                                   //vyhodi xtou krizovatku
                {
                Mapa->node[i].ID=Mapa->node[i+1].ID;
                //Mapa->node[i].order--;
                strcpy(Mapa->node[i].name,Mapa->node[i+1].name);
                Mapa->node[i].neighbour[0]=Mapa->node[i+1].neighbour[0];
                Mapa->node[i].neighbour[1]=Mapa->node[i+1].neighbour[1];
                Mapa->node[i].neighbour[2]=Mapa->node[i+1].neighbour[2];
                Mapa->node[i].neighbour[3]=Mapa->node[i+1].neighbour[3];
                Mapa->node[i].terminal=Mapa->node[i+1].terminal;
                };
        Mapa->count--;
        };


