/*************** Practica 01. Traductor de codigo PseudoHTML ******************
 *
 *  Nombre de Fichero: pr01##.cpp
 *
 *  Proposito: este programa sirve para traducir un archivo escrito en codigo
 *             pseudohtml a codigo html estandar y guardar el resultado en
 *             en un fichero distinto.
 *
 *  Condiciones de Final Anormal y Mensajes de Error y Advertencia
 *
 *  --> No hay final anormal
 *  --> No hay mensajes de error
 *
 *  Historia de Desarrollo:
 *  Fecha     Autor           Id Cambio  Version  Descripcion del cambio
 *  --------  --------------  ---------  -------  ----------------------
 *  25-03-04                          0      1.0
 *            
 *****************************************************************************/

#include <iostream.h>
#include <stdlib.h>
#include <string>
#include <fstream>

const int TAM=100;

struct etiquetas
{
    string html, pseudohtml;
};

typedef etiquetas vector[TAM];

void LeerTabla(ifstream &tabla,vector v,int &i);
void OrdenarTabla(vector &v, int i);
string LeerEtiqueta(ifstream &f);
string TraducirEtiqueta(string &etiqueta,vector v,int i);
void Traducir(ofstream &g,ifstream &f,vector v,int i);
void Salir(bool &fallo);


int main()
{
   string tabla_path, f_path, g_path;  //aqui se guardaran las rutas de los ficheros
   ifstream tabla;
   ifstream f;
   ofstream g;
   vector v;
   int i;
   bool fallo;

   do
   {
      i=-1;
      fallo=false;

      system("cls");

      cout << "--- TRADUCTOR DE CODIGO PSEUDOHTML---\n\n\n";
      cout << "\nIntroduce la ruta del fichero con las equivalencias: ";

      cin >> tabla_path;

      tabla.open(tabla_path.c_str());

      if(!tabla)
      {
         system("cls");
         cout << "Error abriendo " << tabla_path << "\n\n";
         fallo=true;
      }
      else
      {
          LeerTabla(tabla,v,i);
          OrdenarTabla(v,i);

          cout << "\nIntroduce la ruta del fichero a traducir: ";
          cin >> f_path;

          f.open(f_path.c_str());

          if(!f)
          {
              system("cls");
              cout << "Error abriendo " << f_path << "\n\n";
              fallo=true;
              tabla.close();
          }
          else
          {

              cout << "\nIntroduce la ruta del fichero traducido que se va a crear: ";
              cin >> g_path;

              g.open(g_path.c_str());
              if(!g)
              {
                  system("cls");
                  cout << "Error creando" << g_path << "\n\n";
                  fallo=true;
                  f.close();
              }
              else
              {
                 Traducir(g,f,v,i);
                 g.close();
                 f.close();
                 tabla.close();
              }
          }
      }
      if(fallo==false)
      {
            cout << "\n\nEl fichero ha sido traducido\n\n\n";
            Salir(fallo);
      }
      else
            Salir(fallo);

   }while(fallo==true);
   return 0;
}

/*------------------------------------*
*
*  La funcion LeerTabla introduce
*  dentro de un vector de estructuras
*  el contenido del fichero tabla
*
*-------------------------------------*/
void LeerTabla(ifstream &tabla, vector v, int &i)
{
     string aux;
     
     while(tabla >> aux)
     {
          i++;
          v[i].html=aux;

	      tabla >> aux;
	  
	      v[i].pseudohtml=aux;
     }

}

/*--------------------------------------*
*
*  La funcion LeerEtiqueta construye una
*  cadena de caracteres a partir de los
*  caracteres que va leyendo del fichero
*  f hasta encontrar un espacio o un menor
*  que, y al final devuelve esa cadena de
*  caracteres construida
*
*---------------------------------------*/

string LeerEtiqueta(ifstream &f)
{
      char c;
      string etiqueta;

      etiqueta = "<";
 
      c = f.get ();
   
      while (!f.eof () && c != ' ' && c != '>')
      {
          etiqueta += c;
          c = f.get ();
      }

      if (!f.eof () )
         etiqueta += c;

      return etiqueta;

}


/*--------------------------------------------------
*
*  A la funcion TraducirEtiqueta se le proporciona
*  una etiqueta. A continuacion busca esa misma
*  etiqueta dentro del vector de estructuras que
*  contiene la tabla de equivalencias. Cuando la
*  encuentra devuelve la etiqueta equivalente en
*  codigo HTML
*
*--------------------------------------------------*/


string TraducirEtiqueta(string &etiqueta,vector v,int i)
{
	int j=0;
	bool enc=false;

        /*
        el bucle se repite:
        mientras no llegue al final de la longitud del vector Y mientras
        no se haya encontrado la etiqueta Y mientras la etiqueta que
        tenemos sea "alfabeticamente mayor" que las que comprobamos
        en el vector de estructuras
        */

        while((j <= i) && (enc==false) && (etiqueta >= v[j].pseudohtml))
        {
                 if(v[j].pseudohtml==etiqueta)
                 {
                         etiqueta = v[j].html;
                         enc=true;
                 }
		 j++;
       }
       return etiqueta;
}

/*---------------------------------------*
*
*  La funcion Traducir va escribiendo los
*  resultados de la traduccion en un nuevo
*  fichero g
*
*----------------------------------------*/

void Traducir(ofstream &g,ifstream &f,vector v,int i)
{
        char aux;
        string etiqueta;

        while(!f.eof())
        {
           aux = f.get();

           /*
           cuando se encuentre un menor llamamos
           a las funciones que leen la etiqueta
           y la traducen
           */

           if(aux == '<')
           {
              etiqueta = LeerEtiqueta(f);

              etiqueta = TraducirEtiqueta(etiqueta,v,i);

              g << etiqueta; // escribimos en el fichero la etiqueta traducida
           }
           /*
           si no se ha encontrado un menor significa que no es ninguna etiqueta
           que debamos traducir, por lo tanto escribiremos en el fichero el
           caracter que hayamos leido
           */
           else
              /*
              si la ultima etiqueta es </html> significa que se ha llegado
              al final del codigo html y no hay que escribir nada mas, de lo
              contrario nos escribiria un caracter raro
              */
              if(etiqueta != "</html>")
                  g << aux;
        }
}

/*----------------------------------------------------*
*
*  Ordenamos alfabeticamente el vector de estructuras
*  para que la busqueda en él sea más eficiente
*
*----------------------------------------------------*/

void OrdenarTabla(vector &v, int i)
{
    string aux;
    int a=0;
    int b=1;
    int pos;

    while(a<i)
    {
        aux=v[a].pseudohtml;
        while(b<=i)
        {
            if(aux>v[b].pseudohtml)
            {
                pos=b;
                aux=v[pos].pseudohtml;
            }
            b++;
        }

        v[pos].pseudohtml=v[a].pseudohtml;
        v[a].pseudohtml=aux;
        aux=v[pos].html;
        v[pos].html=v[a].html;
        v[a].html=aux;

        a++;
        b=a+1;
    }
}

/*------------------------------------------------
*
*  Esta funcion modifica el valor de la variable
*  fallo para salir del programa en funcion de
*  la respuesta del usuario
*
*-----------------------------------------------*/
void Salir(bool &fallo)
{
     string cadena;

     do{

         cout << "Desea salir del programa? [Si/No]\n> ";
         cin >> cadena;

         if((cadena=="Si")||(cadena=="si")||(cadena=="SI")||(cadena=="sI"))
             fallo=false;
         else
             if((cadena=="No")||(cadena=="no")||(cadena=="NO")||(cadena=="nO"))
                 fallo=true;
             else
                 cout << "\nLa respuesta tiene que ser \"Si\" o \"No\"\n" << endl;

     }while((cadena!="Si")&&(cadena!="si")&&(cadena!="SI")&&(cadena!="sI")&&(cadena!="No")&&(cadena!="no")&&(cadena!="NO")&&(cadena!="nO"));
}