/* File: voli.c */
/* Time-stamp: "2002-06-06 22:22:11 calvanes" */
/* Scopo: uso di strutture e file */

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

/* Strutture di dati */

typedef int bool;
#define TRUE  1
#define FALSE 0

#define LUNGNUM   5
#define LUNGDEST 20

typedef char NumeroVolo[LUNGNUM+1];
typedef char Destinazione[LUNGDEST+1];

struct structOra {
  int ore;
  int minuti;
};
typedef struct structOra Ora;

struct structVolo {
  NumeroVolo numvolo;
  Destinazione destinazione;
  Ora orario;
  int posti;
};
typedef struct structVolo Volo;

struct nodoLista {
  Volo volo;
  struct nodoLista *next;
};
typedef struct nodoLista NodoLista;
typedef NodoLista *ListaVoli;


/* Soluzione esercizio 2 */

ListaVoli leggiVoli(char *nomefile)
{
  FILE *fp;
  Volo volo;
  ListaVoli lista = NULL, aux;

  if ((fp = fopen(nomefile, "r")) == NULL) {
    printf("Non e` possibile aprire in lettura il file %s\n", nomefile);
    exit(1);
  }

  while (fscanf(fp, "%5s %20s %d%*c%d %d", volo.numvolo, volo.destinazione,
                &volo.orario.ore, &volo.orario.minuti, &volo.posti) == 5) {
                           /* inserimento del volo letto in testa alla lista */
    aux = malloc(sizeof(NodoLista));
    aux->volo = volo;
    aux->next = lista;
    lista = aux;
  }

  fclose(fp);
  return lista;
}


void stampaVoli(ListaVoli voli)
{
  printf("\nPartenze voli giornalieri\n"
         "%-5s %-20s %-8s %s\n", "Num", "Destinazione", "Partenza",
         "Posti");
  while (voli != NULL) {
    printf("%-5s %-20s %2d:%2d    %d\n",
           voli->volo.numvolo, voli->volo.destinazione, voli->volo.orario.ore,
           voli->volo.orario.minuti, voli->volo.posti);
    voli = voli->next;
  }
}


/* Soluzione esercizio 3 */

ListaVoli cercaVolo(ListaVoli voli, const char *numVolo)
  /* Restituisce il puntatore al record relativo al volo di numero numVolo, se
     questo e` presente nella lista, NULL altrimenti.
  */
{
  bool trovato = FALSE;

  while (voli != NULL && !trovato)
    if (strcmp(numVolo, voli->volo.numvolo) == 0)
      trovato = TRUE;
    else voli = voli->next;
  return voli;
}


void cambiaOrario(ListaVoli voli, const char *numVolo, Ora nuovaOra)
{
  voli = cercaVolo(voli, numVolo);
  if (voli == NULL)
    printf("\tVolo %s non trovato\n", numVolo);
  else {
    voli->volo.orario.ore = nuovaOra.ore;
    voli->volo.orario.minuti = nuovaOra.minuti;
    printf("\tAggiornato l'orario del volo %s\n", numVolo);
  }
}


void aggiornaPosti(ListaVoli voli, const char *numVolo, int posti)
{
  voli = cercaVolo(voli, numVolo);
  if (voli == NULL)
    printf("\tVolo %s non trovato\n", numVolo);
  else {
    voli->volo.posti = posti;
    printf("\tAggiornato il numero di posti del volo %s\n", numVolo);
  }
}


/* Soluzione esercizio 4 */

bool eliminaVolo(ListaVoli *pvoli, const char *numVolo)
  /* Elimina il volo di numero numVolo dalla lista *pvoli.
     Se il volo e` stato eliminato, restituisce TRUE, altrimenti FALSE.
  */
{
  ListaVoli aux;
  bool eliminato = FALSE;

  if (*pvoli != NULL) {
    if (strcmp(numVolo, (*pvoli)->volo.numvolo) == 0) {
      aux = *pvoli;
      (*pvoli) = (*pvoli)->next;
      free(aux);
      eliminato = TRUE;
    } else
      eliminato = eliminaVolo(&(*pvoli)->next, numVolo);
  }

  return eliminato;
}


/* Funzione main che implementa un semplice menu per eseguire le operazioni
   sviluppate. */

int main(void)
{
  ListaVoli voli;
  NumeroVolo nvolo;
  Ora nuovorario;
  int nposti;
  char nomefile[256], carattere;

  printf("Immetti il nome del file di voli: ");
  scanf("%255s", nomefile);
  scanf("%*[^\n]"); getchar();
  voli = leggiVoli(nomefile);

  do {
    printf("\n\nIntroduci opzione:\n");
    printf("  A ... Cambia orario\n");
    printf("  B ... Aggiorna posti\n");
    printf("  C ... Elimina volo\n");
    printf("  D ... Stampa voli\n");
    printf("  F ... Fine:\n");
    carattere = getchar();
    scanf("%*[^\n]"); getchar();
    switch (carattere) {

    case 'a': case 'A':
      printf("\n\tIntroduci il numero del volo da modificare: ");
      scanf("%5s", nvolo);
      printf("\tIntroduci il nuovo orario (ore minuti): ");
      scanf("%d%d", &nuovorario.ore, &nuovorario.minuti);
      scanf("%*[^\n]"); getchar();
      cambiaOrario(voli, nvolo, nuovorario);
      break;

    case 'b': case 'B':
      printf("\n\t%s", "Introduci il numero del volo da modificare: ");
      scanf("%5s", nvolo);
      printf("\t%s", "Introduci posti prenotati: ");
      scanf("%d", &nposti );
      scanf("%*[^\n]"); getchar();
      aggiornaPosti(voli, nvolo, nposti);
      break;

    case 'c': case 'C':
      printf("\n\tIntroduci il numero del volo da eliminare: ");
      scanf("%5s", nvolo);
      if (eliminaVolo(&voli, nvolo))
        printf("\tEliminato il volo %s\n", nvolo);
      else
        printf("\tVolo %s non trovato\n", nvolo);
      break;

    case 'd': case 'D':
      stampaVoli(voli);
      break;

    case 'f': case 'F':
      break;

    default:
      printf("%s", "Carattere errato");
      break;
    }
  } while (carattere != 'f' && carattere != 'F');

  return 0;
}