package cap19.prestazioni;

import java.util.*;

public class ProfileList implements Profile
{ private static final int N = 100000;
  private interface doStat
  { Statistica apri(int tipo);
    void fai();
    void chiudi(Statistica s, long tempoTrascorso);
  }
  private class InsTesta implements doStat
  { List l;
    public Statistica apri(int tipo)
    { l = liste[tipo];
      return new Statistica("Iserimento in testa");
    }
    public void fai()
    { for (int i = 0; i < (N / 10); i++)
        l.add(i);
    }
    public void chiudi(Statistica s, long tempoTrascorso)
    { s.setTempo((double) tempoTrascorso / (N / 10));
    }
  }
  private class InsCasuale implements doStat
  { List l;
    public Statistica apri(int tipo)
    { l = liste[tipo];
      return new Statistica("Iserimento casuale");
    }
    public void fai()
    { for (int i = 0; i < N; i++)
      { int j = r.nextInt(l.size() + 1);
        l.add(j, i);
      }
    }
    public void chiudi(Statistica s, long tempoTrascorso)
    { s.setTempo((double) tempoTrascorso / N);
    }
  }
  private class RicercaCasuale implements doStat
  { List l;
    int size;
    public Statistica apri(int tipo)
    { l = liste[tipo];
      size = l.size();
      return new Statistica("Ricerca casuale");
    }
    public void fai()
    { for (int i = 0; i < (N / 4); i++)
      { int j = r.nextInt(size);
        l.get(j);
      }
    }
    public void chiudi(Statistica s, long tempoTrascorso)
    { s.setTempo((double) tempoTrascorso / (N / 4));
    }
  }
  private class RimTesta implements doStat
  { List l;
    public Statistica apri(int tipo)
    { l = liste[tipo];
      return new Statistica("Rimozione Testa");
    }
    public void fai()
    { for (int i = 0; i < (N / 10); i++)
        l.remove(0);
    }
    public void chiudi(Statistica s, long tempoTrascorso)
    { s.setTempo((double) tempoTrascorso / (N / 10));
    }
  }
  private class RimCasuale implements doStat
  { List l;
    public Statistica apri(int tipo)
    { l = liste[tipo];
      return new Statistica("Rimozione Casuale");
    }
    public void fai()
    { for (int i = 0; i < (N / 4); i++)
      { int j = r.nextInt(l.size());
        l.remove(j);
      }
    }
    public void chiudi(Statistica s, long tempoTrascorso)
    { s.setTempo((double) tempoTrascorso / (N / 4));
    }
  }
  private class RimIterator implements doStat
  { List l;
    public Statistica apri(int tipo)
    { l = liste[tipo];
      return new Statistica("Rimozione tramite Iterator");
    }
    public void fai()
    { for (int i = 0; i < (N / 4); i++)
      { int j = r.nextInt(l.size() - 1) + 1;
        Iterator k = l.iterator();
        for (int n = 0; n < j; n++)
          k.next();
        k.remove();
      }
    }
    public void chiudi(Statistica s, long tempoTrascorso)
    { s.setTempo((double) tempoTrascorso / (N / 4));
    }
  }
  List[] liste;
  doStat[] tests;
  Random r;
  public ProfileList(List[] liste)
  { this.liste = liste;
    tests = new doStat[6];
    tests[0] = new InsTesta();
    tests[1] = new InsCasuale();
    tests[2] = new RicercaCasuale();
    tests[3] = new RimTesta();
    tests[4] = new RimCasuale();
    tests[5] = new RimIterator();
  }
  public int tipi()
  { return liste.length;
  }
  public Statistica[] start(int tipo, long seme)
  { Statistica[] stats = new Statistica[tests.length];
    r = new Random();
    long start;
    long stop;
    r.setSeed(seme);
    for (int i = 0; i < tests.length; i++)
    { stats[i] = tests[i].apri(tipo);
      start = System.currentTimeMillis();
      tests[i].fai();
      stop = System.currentTimeMillis();
      tests[i].chiudi(stats[i], stop - start);
    }
    return stats;
  }
}
