#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

typedef struct{
    char nombre[40];
    char ciudad[40];
    int edad;
}persona;

typedef struct pers{
    persona p;
    struct pers *sig;
}lista;

void AgregarPersonas(lista **l);
void MostrarPersonas(lista *l);
void GuardarLista(lista *l);
void CargarLista(lista **l);
void BorrarLista(lista **l);

int main()
{
    lista *l=NULL;
    char opcion;

    while(1)
    {
        system("cls");
        printf("********************************************************\n"
               "\tLectura y escritura en binario y listas\n"
               "********************************************************\n");
        printf("1.- Agregar Persona\n"
               "2.- Mostrar Personas\n"
               "3.- Guardar Datos\n"
               "4.- Cargar Datos\n"
               "5.- Salir\n");
        while(opcion=getch(), opcion<'1'||opcion>'5');

        switch(opcion)
        {
            case '1':
                AgregarPersonas(&l);break;
            case '2':
                MostrarPersonas(l);break;
            case '3':
                GuardarLista(l);break;
            case '4':
                CargarLista(&l);break;
            case '5':
                system("pause");return 0;
        }
        system("pause");
    }
}

void AgregarPersonas(lista **l)
{
    lista *rec=NULL, *nodo_nuevo=NULL;

    printf("*************************\n"
           "Agregar Personas\n"
           "*************************\n");

    nodo_nuevo=(lista*)malloc(sizeof(lista)); //Se crea un nodo.

    if(!nodo_nuevo) //Habrá memoria suficiente?
    {
        printf("No hay memoria suficiente.\n");
        return;
    }
    printf("Ingrese Nombre: ");  //Se ingresan datos.
    gets(nodo_nuevo->p.nombre);
    printf("Ingrese ciudad: ");
    gets(nodo_nuevo->p.ciudad);
    printf("Ingrese edad: ");
    scanf("%d", &nodo_nuevo->p.edad);
    fflush(stdin);
    nodo_nuevo->sig=NULL;

    if(!*l) //Si no hay lista la crea.
        *l=nodo_nuevo;
    else{
        rec=*l;  //Se apunta al primer elemento de la lista y se recorre.
        while(rec->sig) //Mientras haya elemento siguiente se avanza en la lista.
            rec=rec->sig;
        rec->sig=nodo_nuevo; //Se agrega nodo al final de la lista.
    }
    return;
}

void MostrarPersonas(lista *l)
{
    lista *rec=NULL;

    printf("*************************\n"
           "Mostrar Personas\n"
           "*************************\n");
    if(!l) //Hay lista?
    {
        printf("No hay personas para mostrar.\n");
        return;
    }

    rec=l; //Rec apunta a l.

    while(rec) //Mientras haya datos para mostrar, se muestran.
    {
        printf("Nombre: %s\n", rec->p.nombre);
        printf("Ciudad: %s\n", rec->p.ciudad);
        printf("Edad: %d\n\n", rec->p.edad);
        rec=rec->sig;
    }

}

void GuardarLista(lista *l)
{
    lista *rec=NULL;
    FILE *archivo;
    printf("*************************\n"
           "Guardar Lista\n"
           "*************************\n");

    archivo=fopen("Lista.dat","wb"); //Abrir archivo para escritura en binario.
    if(!archivo)  //Se pudo abrir archivo?
    {
        printf("No se pudo abrir archivo.\n");
        return;
    }
    rec=l;

    while(rec)  //Mientras haya datos que guardar...
    {
        fwrite(&rec->p,sizeof(persona),1,archivo); //Se escriben en el archivo.
        rec=rec->sig; //Se recorre la lista.
    }

    fclose(archivo); //Se cierra archivo.
    printf("Datos guardados!\n");

}

void CargarLista(lista **l)
{
    lista *nodo_nuevo=NULL,*rec=NULL;
    persona p;
    FILE *archivo=NULL;
    printf("*************************\n"
           "Cargar Lista\n"
           "*************************\n");
    archivo=fopen("Lista.dat","rb");  //Se abre archivo para lectura en binario.
    if(!archivo)
    {
        printf("No se pudo abrir archivo.\n");
        return;
    }

    if(*l) //Si hay lista se elimina.
        BorrarLista(l);

    while(fread(&p, sizeof(persona), 1, archivo)!=0) //Se repite mientras haya datos que leer.
    {
        nodo_nuevo=(lista*)malloc(sizeof(lista));  //Se reseva memoria para crear nodo.
        if(!nodo_nuevo) //Habrá memoria suficiente?
        {
            printf("No se pudo completar el proceso de lectura.\n");
            return;
        }
        nodo_nuevo->p=p;  //El dato contenido en el nodo es igual al dato leído desde el archivo.
        nodo_nuevo->sig=NULL;  //Nodo siguiente apunta a NULL.
        if(!*l){           //Primero se crea la lista
            *l=nodo_nuevo;
            rec=*l;
        }

        else{
            rec->sig=nodo_nuevo;  //Se llena la lista mientras el bucle continúe
            rec=rec->sig;
        }
    }
    fclose(archivo); //Se cierra archivo.
    printf("Carga Exitosa!\n");
}

void BorrarLista(lista **l)
{
    lista *aux=NULL;  //Variable auxiliar
    do{
        aux=(*l)->sig; //Aux es igual al valor siguiente de la lista.
        free(*l); //Se libera la memoria del nodo
        (*l)=aux; //Ahora lista apunta a su valor siguiente
    }while(aux);
}
