import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
import ods.ArrayStack;
import ods.FastArrayStack;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class ListSpeed {

  protected static void pause() {
    System.out.println("Press enter to continue...");
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    try {
      br.readLine();
    } catch (IOException e) {}
  }

  protected static void speedTest(List<Integer> ds, int n, boolean frontOps) {
    long start, stop;
    double elapsed;

    String name = ds.getClass().getName();

    ds.clear();  // make sure the list is empty

    System.out.print(name + ": Adding " + n + " elements to the end...");
    System.out.flush();
    start = System.nanoTime();
    for (int i = 0; i < n; i++) {
      ds.add(i);
    }
    stop = System.nanoTime();
    elapsed = ((double)(stop-start))*1e-9;
    System.out.println("done (" + elapsed + "s)");


    System.out.print(name + ": Removing " + n + " elements from the end...");
    System.out.flush();
    start = System.nanoTime();
    while (!ds.isEmpty()) {
      ds.remove(ds.size()-1);
    }
    stop = System.nanoTime();
    elapsed = ((double)(stop-start))*1e-9;
    System.out.println("done (" + elapsed + "s)");

    if (frontOps) {
      System.out.print(name + ": Adding " + n + " elements to the front...");
      System.out.flush();
      start = System.nanoTime();
      for (int i = 0; i < n; i++) {
        ds.add(0, i);
      }
      stop = System.nanoTime();
      elapsed = ((double)(stop-start))*1e-9;
      System.out.println("done (" + elapsed + "s)");

      System.out.print(name + ": Removing " + n + " elements from the front...");
      System.out.flush();
      start = System.nanoTime();
      while (!ds.isEmpty()) {
        ds.remove(0);
      }
      stop = System.nanoTime();
      elapsed = ((double)(stop-start))*1e-9;
      System.out.println("done (" + elapsed + "s)");
    }
  }

  public static void main(String[] args) {
    int n = 100;
    if (args.length == 1) {
      n = Integer.parseInt(args[0]);
    }

    List<Integer> ds = new ArrayList<>();
    speedTest(ds, n, false);

    System.gc();
    pause();
    ds = new ods.ArrayStack<Integer>(Integer.class);
    speedTest(ds, n, false);

    System.gc();
    pause();
    ds = new ods.FastArrayStack<Integer>(Integer.class);
    speedTest(ds, n, false);

    System.gc();
    pause();
    ds = new LinkedList<Integer>();
    speedTest(ds, n, true);

    System.gc();
    pause();
    ds = new ods.ArrayDeque<Integer>(Integer.class);
    speedTest(ds, n, true);

    System.gc();
    pause();
    ds = new ods.DualArrayDeque<Integer>(Integer.class);
    speedTest(ds, n, true);

  }
}
