class GiocoPersona {
  Gioco gioco;
  Persona persona;
}

public class Ludoteca {

  // Rappresentazione degli oggetti Ludoteca

  // Per rappresentare il nome uso una stringa
  // Per rappresentare i giochi della ludoteca uso una array dinamico
  // (cioe' che ingrandisco e rimpicciolisco secondo le esigenze)
  // di oggetti GiocoPersona

  private String nome;

  final int DIM_INIZIALE = 10;
  private int dim_corrente;
  private int prima_posizione_libera;
  private GiocoPersona[] array;
  

  // Costruttore
  public Ludoteca(String n) {
    nome = n;
    array = new GiocoPersona[DIM_INIZIALE];
    dim_corrente = DIM_INIZIALE;
    prima_posizione_libera = 0;
  }

  // funzioni pubbliche della classe
  public String nome() {
    return nome;
  }

  public boolean presente(Gioco g) {
    for (int i = 0; i < prima_posizione_libera; i++) 
      if (array[i].gioco.equals(g)) return true;
    return false;
  }

  public Persona chiHaIlGioco(Gioco g) {
    for (int i = 0; i < prima_posizione_libera; i++) 
      if (array[i].gioco.equals(g)) return array[i].persona;
    return null;
  }

  public int numeroGiochi() {
    return prima_posizione_libera;
  }

  public int numeroGiochiPrestati() {
    int cont = 0;
    for (int i = 0; i < prima_posizione_libera; i++) 
      if (array[i].persona != null) cont++;
    return cont;
  }

  public void aggiungiGioco(Gioco g) {
    if (presente(g)) return;

    if (prima_posizione_libera == dim_corrente) { //ingrandisci array
      GiocoPersona[] nuovo_array = new GiocoPersona[dim_corrente*2];
      for (int i = 0; i < prima_posizione_libera; i++) 
        nuovo_array[i] = array[i];
      array = nuovo_array;
      dim_corrente = dim_corrente*2;
    }
    array[prima_posizione_libera] = new GiocoPersona();
    array[prima_posizione_libera].gioco = g;
    array[prima_posizione_libera].persona = null;
    prima_posizione_libera++;
  }

  public void eliminaGioco(Gioco g) {
    boolean trovato = false;
    int k = 0;
    while(!trovato && k < prima_posizione_libera)
      if (array[k].gioco.equals(g)) trovato = true;
      else k++;
    if (!trovato) return;
    
    // altrimente l'elemento va eliminato, senza lasciare "buchi" nell'array
    for (int i = k; i < prima_posizione_libera-1; i++)
      array[i] = array[i+1];
    array[prima_posizione_libera-1] = null;
    prima_posizione_libera--;
    
    //se l'array e' troppo vuoto, lo rimpiccioliamo

    if (prima_posizione_libera == dim_corrente/3 &&
        prima_posizione_libera > DIM_INIZIALE) { //rimpiciolisci array
      GiocoPersona[] nuovo_array = new GiocoPersona[dim_corrente/2];
      for (int i = 0; i < prima_posizione_libera; i++) 
        nuovo_array[i] = array[i];
      array = nuovo_array;
      dim_corrente = dim_corrente/2;
    }
  }

  public void prestaGioco(Gioco g, Persona p) {
    for (int i = 0; i < prima_posizione_libera; i++)
      if (array[i].gioco.equals(g)) 
        if (array[i].persona != null) throw new RuntimeException(
          "Errore, prestaGioco: il gioco e' gia' in pretito");
        else {
          array[i].persona = p;
        return;
        }
    throw new RuntimeException(
      "Errore, prestaGioco: il gioco non e' presente");
  }

  public void restituisciGioco(Gioco g) {
    for (int i = 0; i < prima_posizione_libera; i++)
      if (array[i].gioco.equals(g)) 
        if (array[i].persona != null) {
          array[i].persona = null;
          return;
        }
        else 
          throw new RuntimeException(
            "Errore, restituisciGioco: il gioco non e' in prestito");
    throw new RuntimeException(
      "Errore, retituisciGioco: il gioco non e' presente");
  }

  public Gioco[] tuttiIGiochi() {
    Gioco[] ris = new Gioco[prima_posizione_libera];
    for (int i = 0; i < prima_posizione_libera; i++)
      ris[i] = array[i].gioco;
    return ris;
  }   
}
