/**
 * Tests 2 Queue implementations for correctness.
 *
 * @author Zach Tomaszewski
 */
public class QueueTester {

  /**
   * Runs some tests of a queue.  Should print all true in the left column.
   */
  public static void main(String[] args) {
    boolean ok = true;
    System.out.println("***Linear Queue***");
    ok = ok && testQueue(new LinearQueue<Integer>());
    System.out.println("\n***Circular Queue***");
    ok = ok && testQueue(new CircularQueue<Integer>());

    System.out.print("\nDONE: ");
    System.out.println((ok) ? "PASSED ALL" : "Failed a test.");
  }

  /** Given an empty queue, runs some tests, printing results to the screen. */
  private static boolean testQueue(Queue<Integer> q) {
    int size = 0;
    //empty queue behavior
    System.out.print("\t\tEmpty queue. ");
    boolean ok = testQueueState(q, size, 0, "[]");

    ok = ok && testOffer(q, 3, ++size, 3, "[3]");
    ok = ok && testOffer(q, 5, ++size, 3, "[3, 5]");
    ok = ok && testOffer(q, 7, ++size, 3, "[3, 5, 7]");

    ok = ok && testPoll(q, --size, 5, "[5, 7]");
    ok = ok && testOffer(q, 9, ++size, 5, "[5, 7, 9]");
    ok = ok && testPoll(q, --size, 7, "[7, 9]");
    ok = ok && testPoll(q, --size, 9, "[9]");
    ok = ok && testPoll(q, --size, 0, "[]");

    ok = ok && testOffer(q, 2, ++size, 2, "[2]");
    ok = ok && testOffer(q, 4, ++size, 2, "[2, 4]");
    return ok;
  }

  /**
   * Offers the given val to the given queue, then tests whether it has
   * the given state.
   *
   * @see #testQueueState
   */
  private static boolean testOffer(Queue<Integer> q, int val,
                                int size, int front, String str) {
    System.out.print("\t\tOffering " + val + ".  ");
    q.offer(val);
    return testQueueState(q, size, front, str);
  }

  /**
   * Polls the given queue and then checks whether it has the given state.
   *
   * @see #testQueueState
   */
  private static boolean testPoll(Queue<Integer> q,
                                int size, int front, String str) {
    System.out.print("\t\tPolling ");
    int returned = q.poll();
    System.out.print(returned + ". ");
    return testQueueState(q, size, front, str);
  }

  /**
   * Tests whether the given Queue has the given size, front element,
   * and toString() format.  If expected size is 0, front
   * will be ignored and will check that peek() throws an exception instead.
   */
  private static boolean testQueueState(Queue<Integer> q,
                                     int size, int front, String str) {
    boolean ok = true;
    System.out.println("Queue now size " + q.size() + ": " + q);

    boolean strTest = q.toString().equals(str);
    System.out.println(strTest + " (toString)");
    ok = ok && strTest;

    boolean sizeTest = (q.size() == size);
    System.out.println(sizeTest + " (size)");
    ok = ok && sizeTest;

    boolean peekTest;
    if (size != 0) {
       peekTest = q.peek().equals(front);
    }else {
      try {
        q.peek();
        peekTest = false;
      }catch (IllegalStateException e) {
        peekTest = true;
      }
    }
    System.out.println(peekTest + " (peek)");
    ok = ok && peekTest;
    return ok;
  }
}