#ifndef _TSCREENINFO_CPP_
#define _TSCREENINFO_CPP_

#include "escenarios.h"

REGISTER_CLASS_ID(TEstadoEnemigo);
REGISTER_CLASS_ID(TScreenInfo);

TEstadoEnemigo::TEstadoEnemigo()
{
    tipo = NADA;
    vivo=false;
}

TScreenInfo::TScreenInfo()
{
    left=0; top=0;
	right=0; bottom=0;
	cofre=SIN_COFRE;
	tipo_tesoro=SIN_TESORO;
	visitada=false; calculado = false;
	posx=0; posy=0;
}

void TScreenInfo::ordenateTreasures(TScreenInfo *GA_InfoScr)
{
    int i,j,id_scr;
    
    // Indices de las pantallas donde se encuentran los cofres.
    //
    int indices[40]= {
         24, 42, 37, 39,  8, 11, 19, 36, 47,193,
        233, 52,186,189, 56,182,155, 60, 77, 75,
        177,160, 68, 78,174,145,213,132,135,116,
        110,105, 98, 95, 88,125,115,107, 97,121
    };

    // Contadores de tesoros a repartir
    //
    int contadores[13]={
        1,      // (0)  Una Gema Roja
        1,      // (1)  Una Gema Verde
        1,      // (2)  Una Gema Azul
        1,      // (3)  Una Llave Roja
        1,      // (4)  Una Llave Azul
        1,      // (5)  Pocion Amarilla
        1,      // (6)  Pocion Verde
        5,      // (7)  Cinco Bolsas de Oro
        6,      // (8)  Cajas de Flechas
        3,      // (9)  Tres vidas extra
        6,      // (10) Hechizos de Cerdo
        7,      // (11) Siete Arañas o Arqueros
        6       // (12) Murcielagos o Lanceros
    };

    // Borramos la información de tesoros de todas las pantallas.
    //
    for (i=0;i<MAX_PANTALLAS;i++)
    {
        GA_InfoScr[i].cofre=SIN_COFRE;
        GA_InfoScr[i].tipo_tesoro=SIN_TESORO;
    }

    // Colocamos los tesoros, a excepción de los murcielagos
    // o lanceros, que rellenaran los huecos que queden libres.
    //
    for (i=0;i<12;i++)
    {
        for (j=0;j<contadores[i];j++)
        {
            do
            {
                id_scr = indices[TSpriteGlaurung::miRND.nextInt(40)];
                
                // Caso que la pantalla ya se haya rellenado.
                //
                if (GA_InfoScr[id_scr].cofre!=SIN_COFRE)
                {
                    // Indicamos que aun no se ha colocado el cofre.
                    //
                    id_scr=0;
                }
                else
                {
                    // Evitamos que la llave azul, se coloque en el cofre
                    // que esta detras de la puerta azul, porque sería
                    // imposible coger la llave.
                    //
                    if (id_scr==75 && i==4)
                    {
                        // Indicamos que aun no se ha colocado el cofre.
                        //
                        id_scr=0;
                    }
                    else
                    {
                        GA_InfoScr[id_scr].cofre=COFRE_CERRADO;
                        GA_InfoScr[id_scr].tipo_tesoro = (i+1);
                    }
                }
            }while (id_scr==0);
        }
    }

    // Ahora, en las pantallas que queden sin poner aun el tesoro,
    // colocamos el tipo de tesoro BAT_LANCERO
    //
    for (i=0;i<40;i++)
    {
        id_scr = indices[i];

        if (GA_InfoScr[id_scr].cofre == SIN_COFRE)
        {
            GA_InfoScr[id_scr].cofre=COFRE_CERRADO;
            GA_InfoScr[id_scr].tipo_tesoro=BAT_LANCERO;
        }
    }
    
    GA_InfoScr[8].tipo_tesoro=BAT_LANCERO;
}

TScreenInfo* TScreenInfo::getScreenInfo(void)
{
    FILE *f;
	int i,lscr,lleft,ltop,lright,lbottom;
	char t0,t1,t2,t3,t4,t5;

    f=fopen("Data/Salidas.dat","rt");
    if (!f) return NULL;
    
    PScreenInfo GA_InfoScr = new TScreenInfo[MAX_PANTALLAS];
    
    while (!feof(f))
	{
		fscanf(f,"%u.{%u,%u,%u,%u}.{'%c','%c','%c','%c'}.{'%c','%c'}\n"
			,&lscr,&lleft,&ltop,&lright,&lbottom
			,&t0,&t1,&t2,&t3,&t4,&t5);

		GA_InfoScr[lscr].left = lleft;
		GA_InfoScr[lscr].right = lright;
		GA_InfoScr[lscr].top = ltop;
		GA_InfoScr[lscr].bottom = lbottom;

		GA_InfoScr[lscr].enemigos[0].tipo=t0;
		GA_InfoScr[lscr].enemigos[1].tipo=t1;
		GA_InfoScr[lscr].enemigos[2].tipo=t2;
		GA_InfoScr[lscr].enemigos[3].tipo=t3;
		GA_InfoScr[lscr].enemigos[4].tipo=t4;
		GA_InfoScr[lscr].enemigos[5].tipo=t5;

		for (i=0;i<MAX_ENEMIGOS;i++)
		{
			GA_InfoScr[lscr].enemigos[i].vivo = (GA_InfoScr[lscr].enemigos[i].tipo!=TEstadoEnemigo::NADA);
		}
	}
	
	fclose(f);
	
	ordenateTreasures(GA_InfoScr);
	generateMap(GA_InfoScr);
	return GA_InfoScr;
}

void TScreenInfo::readFromFile(FILE* f)
{
    fread(&cofre,sizeof(cofre),1,f);
    fread(&tipo_tesoro,sizeof(tipo_tesoro),1,f);
    fread(&visitada,sizeof(visitada),1,f);
    
    for (int i=0;i<MAX_ENEMIGOS;i++)
	{
		fread(&enemigos[i].vivo,sizeof(enemigos[i].vivo),1,f);
		fread(&enemigos[i].tipo,sizeof(enemigos[i].tipo),1,f);
	}	
}

void TScreenInfo::writeToFile(FILE* f)
{
    fwrite(&cofre,sizeof(cofre),1,f);
    fwrite(&tipo_tesoro,sizeof(tipo_tesoro),1,f);
    fwrite(&visitada,sizeof(visitada),1,f);
    
    for (int i=0;i<MAX_ENEMIGOS;i++)
	{
		fwrite(&enemigos[i].vivo,sizeof(enemigos[i].vivo),1,f);
		fwrite(&enemigos[i].tipo,sizeof(enemigos[i].tipo),1,f);
	}	
}

void TScreenInfo::readFromFile(FILE *f,TScreenInfo *si)
{
    for (int i=0;i<MAX_PANTALLAS;i++)
	{
        si[i].readFromFile(f);
	}	
}

void TScreenInfo::writeToFile(FILE *f,TScreenInfo *si)
{
    for (int i=0;i<MAX_PANTALLAS;i++)
	{
        si[i].writeToFile(f);
	}	
}

void TScreenInfo::calculateScreenMap(TScreenInfo* scr,int i)
{
     char buff[200];
     
     // Estas dos lineas, debene estar, porque son las
     // la pantalla 66 es la unica desligada del mapa.
     // Hay que calcular primero la 67, para luego poder
     // calcular la 66.
     //
     if (i==67) i=66;
     else if (i==66) i=67;
     
     if (scr[i].left!=-1)
     {
      if (scr[scr[i].left].right!=i)
      {
       sprintf(buff,"Incoherencia LEFT (%i).",i);
       allegro_message(buff);
      }
     }
     
     if (scr[i].top!=-1)
     {
      if (scr[scr[i].top].bottom!=i)
      {
       sprintf(buff,"Incoherencia TOP (%i).",i);
       allegro_message(buff);
      }
     }
     
     if (scr[i].right!=-1)
     {
      if (scr[scr[i].right].left!=i)
      {
       sprintf(buff,"Incoherencia RIGHT (%i).",i);
       allegro_message(buff);
      }
     }
     
     if (scr[i].bottom!=-1)
     {
      if (scr[scr[i].bottom].top!=i)
      {
       sprintf(buff,"Incoherencia BOTTOM (%i).",i);
       allegro_message(buff);
      }
     }
              
     // Calculamos la coordenada de la pantalla en el mapa
     // a partir de una pantalla adyacente
     //
     if (scr[i].left!=-1 && !scr[i].calculado)
     {
      if (scr[scr[i].left].calculado)
      {
       scr[i].posx = scr[scr[i].left].posx+1;
       scr[i].posy = scr[scr[i].left].posy;
       scr[i].calculado=true;
      }
     }
     
     if (scr[i].top!=-1 && !scr[i].calculado)
     {
      if (scr[scr[i].top].calculado)
      {
       scr[i].posx = scr[scr[i].top].posx;
       scr[i].posy = scr[scr[i].top].posy+1;
       scr[i].calculado=true;
      }
     }
     
     if (scr[i].right!=-1 && !scr[i].calculado)
     {
      if (scr[scr[i].right].calculado)
      {
       scr[i].posx = scr[scr[i].right].posx-1;
       scr[i].posy = scr[scr[i].right].posy;
       scr[i].calculado=true;
      }
     }
     
     if (scr[i].bottom!=-1 && !scr[i].calculado)
     {
      if (scr[scr[i].bottom].calculado)
      {
       scr[i].posx = scr[scr[i].bottom].posx;
       scr[i].posy = scr[scr[i].bottom].posy-1;
       scr[i].calculado=true;
      }
     }
     scr[i].calculado=true;
}

void TScreenInfo::generateMap(TScreenInfo *scr)
{
     // Genera el aspecto grafico del mapa
     //
     for (int i=0;i<MAX_PANTALLAS;i++)
     {
         calculateScreenMap(scr,i);
         scr[i].visitada=false;
     }
     //saveDebug(scr,"depura.txt");
}

void TScreenInfo::saveDebug(TScreenInfo *scr,const char *name)
{
    FILE *f=fopen(name,"wt");
    if (f)
    {
        for (int i=0;i<MAX_PANTALLAS;i++)
        {
             fprintf(f,"[%i] px=%i py=%i (%i,%i,%i,%i)\n",i,scr[i].posx,scr[i].posy,scr[i].left,scr[i].top,scr[i].right,scr[i].bottom);
        }
        fclose(f);
    }
}

#endif
