/** Test Sequences CircularArray, SLList and DLList */

package FlexOr.container;

import java.util.Date;

public class SequencesTest {
  
  public static void main (String arg[]) {
    println("Test started " + new Date());
    println("**** Singly linked list");
    testSLL();
    println("**** Doubly linked list");
    testDLL();
    println("**** Circular array");
    testCA();
    println("Test finished " + new Date());
  }

  public static void testSLL() {
    SLList list = new SLList();  verifyEmpty("1", list);
    list.add("a");     verifyL1("2", list, "[ a ]", "a", "a");
    list.remove("a");  verifyEmpty("3", list);
    try { list.remove(); }
    catch (ContainerEmptyException e)
      { println("3a Caught container empty exception"); }

    list.add("a");
    list.add("b");     verifyL2("4", list, "[ a b ]", "a", "b");
    if (list.contains("c")) println("5 shouldn't to contain c");
    if (!list.contains("a")) println("6 should contain a");
    if (!list.contains("b")) println("7 should contain b");
    list.add("c");           verifyL3("8", list, "[ a b c ]", "a", "c");
    list.remove("b");        verifyL2("9", list, "[ a c ]", "a", "c");
    list.insertAt("b", 0);   verifyL3("10", list, "[ b a c ]", "b", "c");
    list.remove("b");        verifyL2("11", list, "[ a c ]", "a", "c");
    list.insertAt("b", 1);   verifyL3("12", list, "[ a b c ]", "a", "c");
    list.remove("b");        verifyL2("13", list, "[ a c ]", "a", "c");
    list.insertAt("b", 2);   verifyL3("14", list, "[ a c b ]", "a", "b");
    list.setAt("d", 0);      verifyL3("15", list, "[ d c b ]", "d", "b");
    list.setAt("e", 2);      verifyL3("16", list, "[ d c e ]", "d", "e");
    verifyAt("17", list, "d", 0);
    verifyAt("18", list, "c", 1);
    verifyAt("19", list, "e", 2);
    try { verifyAt("20", list, "a", -1);
    } catch (SequenceIndexException e) { println("21 Index under exception"); }
    try { verifyAt("22", list, "a", 3);
    } catch (SequenceIndexException e) { println("23 Index over exception"); }
    if (!list.contains("e",2)) println("24 should contain e");
    if (!list.contains("e",1)) println("25 should contain e");
    if (list.contains("f",1))  println("26 should not contain f");
    
    SLList list2 = new SLList();
    list2.add("d"); list2.add("c"); list2.add("e");
    if (!list.equals(list2)) println("28 " + list.toString() +
      " should equal " + list2.toString());
    list2.setAt("f",2);
    if (list.equals(list2)) println("29 " + list.toString() +
      " should not be equal " + list2.toString());
      
    if (list.indexOf("e") != 2) println("30 invalid index for e of " +
          list.indexOf("e"));
    if (list.indexOf("e",1) != 2) println("31 invalid index for e of " +
          list.indexOf("e"));
    if (list.indexOf("f") != -1) println("30 invalid index for f of " +
          list.indexOf("f"));

    list2 = (SLList) list.clone();
    verifyL3("31", list2, "[ d c e ]", "d", "e");
    list.add("a"); list.add("b");
    println("34 " + list.toString());
    list.removeAt(0);  // Down to length 4
    list.removeAt(3);  // Down to length 3
    verifyL3("35", list, "[ c e a ]", "c", "a");
    list.removeAt(1);  // Down to length 2
    verifyL2("36", list, "[ c a ]", "c", "a");
  }

  public static void testDLL() {
    DLList list = new DLList();  verifyEmpty("1", list);
    list.add("a");     verifyL1("2", list, "[ a ]", "a", "a");
    list.remove("a");  verifyEmpty("3", list);
    try { list.remove(); }
    catch (ContainerEmptyException e)
      { println("3a Caught container empty exception"); }

    list.add("a");
    list.add("b");     verifyL2("4", list, "[ a b ]", "a", "b");
    if (list.contains("c")) println("5 shouldn't to contain c");
    if (!list.contains("a")) println("6 should contain a");
    if (!list.contains("b")) println("7 should contain b");
    list.add("c");           verifyL3("8", list, "[ a b c ]", "a", "c");
    list.remove("b");        verifyL2("9", list, "[ a c ]", "a", "c");
    list.insertAt("b", 0);   verifyL3("10", list, "[ b a c ]", "b", "c");
    list.remove("b");        verifyL2("11", list, "[ a c ]", "a", "c");
    list.insertAt("b", 1);   verifyL3("12", list, "[ a b c ]", "a", "c");
    list.remove("b");        verifyL2("13", list, "[ a c ]", "a", "c");
    list.insertAt("b", 2);   verifyL3("14", list, "[ a c b ]", "a", "b");
    list.setAt("d", 0);      verifyL3("15", list, "[ d c b ]", "d", "b");
    list.setAt("e", 2);      verifyL3("16", list, "[ d c e ]", "d", "e");
    verifyAt("17", list, "d", 0);
    verifyAt("18", list, "c", 1);
    verifyAt("19", list, "e", 2);
    try { verifyAt("20", list, "a", -1);
    } catch (SequenceIndexException e) { println("21 Index under exception"); }
    try { verifyAt("22", list, "a", 3);
    } catch (SequenceIndexException e) { println("23 Index over exception"); }
    if (!list.contains("e",2)) println("24 should contain e");
    if (!list.contains("e",1)) println("25 should contain e");
    if (list.contains("f",1))  println("26 should not contain f");
    
    DLList list2 = new DLList();
    list2.add("d"); list2.add("c"); list2.add("e");
    if (!list.equals(list2)) println("28 " + list.toString() +
      " should equal " + list2.toString());
    list2.setAt("f",2);
    if (list.equals(list2)) println("29 " + list.toString() +
      " should not be equal " + list2.toString());      
    if (list.indexOf("e") != 2) println("30 invalid index for e of " +
          list.indexOf("e"));
    if (list.indexOf("e",1) != 2) println("31 invalid index for e of " +
          list.indexOf("e"));
    if (list.indexOf("f") != -1) println("30 invalid index for f of " +
          list.indexOf("f"));
    list2 = (DLList) list.clone();
    verifyL3("31", list2, "[ d c e ]", "d", "e");
    list.add("a"); list.add("b");
    println("34 " + list.toString());
    list.removeAt(0);  // Down to length 4
    list.removeAt(3);  // Down to length 3
    verifyL3("35", list, "[ c e a ]", "c", "a");
    list.removeAt(1);  // Down to length 2
    verifyL2("36", list, "[ c a ]", "c", "a");
  }

  public static void testCA() {
    CircularArray list = new CircularArray(5);  verifyEmpty("1", list);
    list.add("a");     verifyL1("2", list, "[ a ]", "a", "a");
    list.remove("a");  verifyEmpty("3", list);
    try { list.remove(); }
    catch (ContainerEmptyException e)
      { println("3a Caught container empty exception"); }

    list.add("a");
    list.add("b");     verifyL2("4", list, "[ a b ]", "a", "b");
    if (list.contains("c")) println("5 shouldn't to contain c");
    if (!list.contains("a")) println("6 should contain a");
    if (!list.contains("b")) println("7 should contain b");
    list.add("c");           verifyL3("8", list, "[ a b c ]", "a", "c");
    list.remove("b");        verifyL2("9", list, "[ a c ]", "a", "c");
    list.insertAt("b", 0);   verifyL3("10", list, "[ b a c ]", "b", "c");
    list.remove("b");        verifyL2("11", list, "[ a c ]", "a", "c");
    list.insertAt("b", 1);   verifyL3("12", list, "[ a b c ]", "a", "c");
    list.remove("b");        verifyL2("13", list, "[ a c ]", "a", "c");
    list.insertAt("b", 2);   verifyL3("14", list, "[ a c b ]", "a", "b");
    list.setAt("d", 0);      verifyL3("15", list, "[ d c b ]", "d", "b");
    list.setAt("e", 2);      verifyL3("16", list, "[ d c e ]", "d", "e");
    verifyAt("17", list, "d", 0);
    verifyAt("18", list, "c", 1);
    verifyAt("19", list, "e", 2);
    try { verifyAt("20", list, "a", -1);
    } catch (SequenceIndexException e) { println("21 Index under exception"); }
    try { verifyAt("22", list, "a", 3);
    } catch (SequenceIndexException e) { println("23 Index over exception"); }
    if (!list.contains("e",2)) println("24 should contain e");
    if (!list.contains("e",1)) println("25 should contain e");
    if (list.contains("f",1))  println("26 should not contain f");
    
    CircularArray list2 = new CircularArray(5);
    list2.add("d"); list2.add("c"); list2.add("e");
    if (!list.equals(list2)) println("28 " + list.toString() +
      " should equal " + list2.toString());
    list2.setAt("f",2);
    if (list.equals(list2)) println("29 " + list.toString() +
      " should not be equal " + list2.toString());
      
    if (list.indexOf("e") != 2) println("30 invalid index for e of " +
          list.indexOf("e"));
    if (list.indexOf("e",1) != 2) println("31 invalid index for e of " +
          list.indexOf("e"));
    if (list.indexOf("f") != -1) println("30 invalid index for f of " +
          list.indexOf("f"));

    list2 = (CircularArray) list.clone();
    verifyL3("31", list2, "[ d c e ]", "d", "e");

    list.add("a"); list.add("b");
    try { list.add("f");
    } catch (ContainerFullException e) {
      println("33 Container full exception");
    }
    println("34 " + list.toString());
    list.removeAt(0);  // Down to length 4
    list.removeAt(3);  // Down to length 3
    verifyL3("35", list, "[ c e a ]", "c", "a");
    list.removeAt(1);  // Down to length 2
    verifyL2("36", list, "[ c a ]", "c", "a");
  }

  private static void println(String item) {
    System.out.println(item);
  }
  
  private static void verifyAt(String id, Sequence list, String item,
                              int index) {
    if ( !((String)list.elementAt(index)).equals(item))
      println(id + "Wrong element " + list.elementAt(index) + " at " +
            index + " should be " + item);
  }
  
  private static void verifyEmpty(String index, Sequence list) {
    String expected = "[]";
    if (! list.toString().equals(expected))
      println(index + "Invalid contents: " + list.toString() + " " + expected);
    if (list.size() != 0) println(index + "size not 0");
    if (list.firstElement() != null)
      println(index + "first element not null");
    if (list.lastElement() !=null)
      println(index + "last element not null");
    if (! list.isEmpty())
      println(index + "Empty list is said to be not empty");
  }
  
  private static void verifyL1(String index, Sequence list, String expected,
        String first, String last) {
    if (! list.toString().equals(expected))
      println(index + "Invalid contents: " + list.toString() +
       " " + expected);
    if (list.size() != 1) println(index + "size not 1");
    if (list.firstElement() != first)
        println(index + "first element not " + first +
         " but " + list.firstElement());
    if (list.lastElement() != last)
        println(index + "last element not " + last +
         " but " + list.lastElement());
  }
  
  private static void verifyL2(String index, Sequence list, String expected,
        String first, String last) {
    if (! list.toString().equals(expected))
      println(index + "Invalid contents: " + list.toString() +
       " " + expected);
    if (list.size() != 2) println(index + "size not 2");
    if (list.firstElement() != first)
        println(index + "first element not " + first +
         " but " + list.firstElement());
    if (list.lastElement() != last)
        println(index + "last element not " + last +
         " but " + list.lastElement());
  }
  
  private static void verifyL3(String index, Sequence list, String expected,
        String first, String last) {
    if (! list.toString().equals(expected))
      println(index + "Invalid contents: " + list.toString() +
       " " + expected);
    if (list.size() != 3) println(index + "size not 3");
    if (list.firstElement() != first)
        println(index + "first element not " + first +
         " but " + list.firstElement());
    if (list.lastElement() != last)
        println(index + "last element not " + last +
         " but " + list.lastElement());
  }
}
