package editortrees;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

public class EditTreeTest {
	
	static int points = 0;
	
	// Feel free to use these strings in your test cases, or not.
	
	static String s1 = "short string",
	       s2 = "a moderately short string",
	       s3 = "This string is not as short as the others",
	       s4 = "This is a great, big, juicy, longer-than-the-others, string",
	       s5 = "You can't always get the strings you want, " +
	            "but if you try sometimes, you just might find you get the strings you need.";
	
	/** The variables whose first two digits are your team number are available 
	 * for your team's test cases to use.  If you want to intiialize them once and for all instead of in individual test cases, 
	 * put that code in setUpXY, where XY is your team number.
	 * You may use other variables, of course, but they should be local to your methods.
	 */
	EditTree t110, t111, t112, t113, t114, t115, t116, t117, t118, t119;
	EditTree t120, t121, t122, t123, t124, t125, t126, t127, t128, t129;
	EditTree t130, t131, t132, t133, t134, t135, t136, t137, t138, t139;
	EditTree t140, t141, t142, t143, t144, t145, t146, t147, t148, t149;
	EditTree t150, t151, t152, t153, t154, t155, t156, t157, t158, t159;
	EditTree t160, t161, t162, t163, t164, t165, t166, t167, t168, t169;
	EditTree t210, t211, t212, t213, t214, t215, t216, t217, t218, t219;
	EditTree t220, t221, t222, t223, t224, t225, t226, t227, t228, t229;
	EditTree t230, t231, t232, t233, t234, t235, t236, t237, t238, t239;
	EditTree t240, t241, t242, t243, t244, t245, t246, t247, t248, t249;
	EditTree t250, t251, t252, t253, t254, t255, t256, t257, t258, t259;
	EditTree t260, t261, t262, t263, t264, t265, t266, t267, t268, t269;
	EditTree ti0, ti1, ti2, ti3, ti4, ti5, ti6, ti7, ti8, ti9;
	
	// Do not modify this method


	@Before
	public void setUp() throws Exception {
	    try {
		setUpInstructors();
	    } catch (Exception e) {
		System.out.println("Error in setUpInstructors:");
		e.printStackTrace();
	    }
	    try {
		setUp11();
	    } catch (Exception e) {
		System.out.println("Error in setUp11:");
		e.printStackTrace();
	    }
	    try {
		setUp12();
	    } catch (Exception e) {
		System.out.println("Error in setUp12:");
		e.printStackTrace();
	    }
	    try {
		setUp13();
	    } catch (Exception e) {
		System.out.println("Error in setUp13:");
		e.printStackTrace();
	    }
	    try {
		setUp14();
	    } catch (Exception e) {
		System.out.println("Error in setUp14:");
		e.printStackTrace();
	    }
	    try {
		setUp15();
	    } catch (Exception e) {
		System.out.println("Error in setUp15:");
		e.printStackTrace();
	    }
	    try {
		setUp16();
	    } catch (Exception e) {
		System.out.println("Error in setUp16:");
		e.printStackTrace();
	    }
	    try {
		setUp21();
	    } catch (Exception e) {
		System.out.println("Error in setUp21:");
		e.printStackTrace();
	    }
	    try {
		setUp22();
	    } catch (Exception e) {
		System.out.println("Error in setUp22:");
		e.printStackTrace();
	    }
	    try {
		setUp23();
	    } catch (Exception e) {
		System.out.println("Error in setUp23:");
		e.printStackTrace();
	    }
	    try {
		setUp24();
	    } catch (Exception e) {
		System.out.println("Error in setUp24:");
		e.printStackTrace();
	    }
	    try {
		setUp25();
	    } catch (Exception e) {
		System.out.println("Error in setUp25:");
		e.printStackTrace();
	    }
	    try {
		setUp26();
	    } catch (Exception e) {
		System.out.println("Error in setUp26:");
		e.printStackTrace();
	    }
	}

	

	public void setUpInstructors() throws Exception {

	}

	public void setUp11() throws Exception {

	}

	public void setUp12() throws Exception {
		
	}

	public void setUp13() throws Exception {
		
	}

	public void setUp14() throws Exception {
		
	}

	public void setUp15() throws Exception {
		
	}

	public void setUp16() throws Exception {
		
	}

	public void setUp21() throws Exception {
		
	}

	public void setUp22() throws Exception {
		
	}

	public void setUp23() throws Exception {
		
	}

	public void setUp24() throws Exception {
		
	}

	public void setUp25() throws Exception {
		t250 = new EditTree();
		t251 = new EditTree();
		t251.add('a',0);
		t252 = new EditTree();
		t252.add('a',0);
		t252.add('b');
		t252.add('c',0);
		t253 = new EditTree();
		t253.add('a');
		t253.add('p');
		t253.add('e');
		t253.add('r');
		t253.add('s');
		t253.add('o');
		t253.add('n');
		t254 = new EditTree();
		t254.add('a');
		t254.add('t');
		reinitialize5();
		reinitialize6();
		t257 = new EditTree();
		t257.add('I');
		t257.add(' ');
		t257.add('s');
		t257.add(' ');
		t257.add('t', 1);
		t257.add('3');
		t257.add('m');
		t257.add('a', 6);
		t257.add('i',3);
		t258 = new EditTree();
		t258.add('I');
		t258.getRoot().rank = 7;
		t258.add('3');
	}
	
	private void reinitialize5() {
		t255 = new EditTree();
		t255.add('l');
		t255.add('f');
	}
	
	private void reinitialize6() {
		t256 = new EditTree();
		t256.add('t');
		t256.add('i', 0);
	}

	public void setUp26() throws Exception {
		
	}

	// The name of each of your team's tests should end with an underscore
	// followed by your team number, 
	// for example, testSize3_13 if you are on team 13.
	
	// Make sure that each of your tests has a timeout.  
	// The timeout should be 1 or 2 seconds unless your
	// test involves VERY complicated operations.
	
	// Each of your tests should be worth one point.
	
	// A sample test to remind you of the format:
	
	@Test(timeout=1000) // one second
	public void testSize3_i() {  // i is for instructor
		ti3 = new EditTree(s1);
		assertEquals(12, ti3.size());
		points += 1; // only incremented if test passes.
	}
	
	@Test(timeout=1000)
	public void testSize0_25(){
		assertEquals(0, t250.size());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testHeight0_25(){
		assertEquals(-1, t250.height());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testSize1_25(){
		assertEquals(1, t251.size());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testHeight1_25(){
		assertEquals(0, t251.height());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testSize2_25(){
		assertEquals(3, t252.size());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testHeight2_25(){
		assertEquals(1, t252.height());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testRank1_25(){
		assertTrue(t251.checkRanks());
		// Comment the next line out if a null node was used instead.
		assertEquals(null, t251.getRoot().left);
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testRank2_25(){
		assertTrue(t252.checkRanks());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testRank3_25(){
		assertTrue(t253.checkRanks());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testNoHeightChange_25(){
		int before = t254.height();
		t254.add('c', 0);
		int after = t254.height();
		assertEquals(before, after);
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testHeightChange_25(){
		int before = t254.height();
		t254.add('s');
		int after = t254.height();
		assertEquals(before + 1, after);
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testSingleLeft_25(){
		t255.add('t');
		assertEquals(t255.getRoot().element, 'f');
		reinitialize5();
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testSingleRight_25(){
		t256.add('r', 0);
		assertEquals(t255.getRoot().element, 'i');
		reinitialize6();
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testDoubleLeft_25(){
		t255.add('f', 1);
		assertEquals(t255.getRoot().element, 'f');
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testDoubleRight_25(){
		t256.add('g', 1);
		assertEquals(t255.getRoot().element, 'g');
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testOutOfBounds_25(){
		try {
			t256.add('-', -1);
		} catch (IndexOutOfBoundsException iob) {
			points += 1;
		}
	}
	
	@Test(timeout=1000)
	public void testToString2_25(){
		assertEquals("cab", t252.toString());
		points += 1;
	}

	@Test(timeout=1000)
	public void testToString3_25(){
		assertEquals("aperson", t253.toString());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testDelete1_25(){
		assertEquals(2, t253.height());
		assertEquals(7, t253.size());
		assertEquals('a', t253.delete(0));
		assertEquals(2, t253.height());
		assertEquals(6, t253.size());
		assertTrue(t253.isHeightBalanced());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testToString4_25(){
		assertEquals("person", t253.toString());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testDelete2_25(){
		assertEquals('e', t253.delete(1));
		assertEquals('s', t253.delete(2));
		t253.add('e');
		assertEquals("prone",t253.toString());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testNoChange_25(){
		// I don't know for sure if this is a way to compare a tree to its past
		// self, but if not then I don't know how to test this case. Also the
		// equals method needs to be implemented first.
		assertEquals(t254, addDel(t254));
		points += 1;
	}
	
	private EditTree addDel(EditTree t) {
		// Used only in testNoChange_25()
		t.add('s', 0);
		t.delete(0);
		return t;
	}
	
	@Test(timeout=1000)
	public void testChange_25(){
		assertFalse(t254.equals(delAdd(t254)));
		points += 1;
	}
	
	private EditTree delAdd(EditTree t) {
		// Used only in testChange_25()
		t.delete(0);
		t.add('c', 0);
		return t;
	}

	@Test(timeout=1000)
	public void testStringConstructorAndConcatenate1_25(){
		t254.concatenate(new EditTree("ball"));
		assertEquals("football",t254.toString());
		assertTrue(t254.isHeightBalanced());
		points += 1;
	}
	
	@Test(timeout=1000,expected=IllegalArgumentException.class)
	public void testConcatenateException1_25(){
		t254.concatenate(new EditTree("football"));
		points += 1;
	}
	
	@Test(timeout=1000,expected=IndexOutOfBoundsException.class)
	public void testSplitException1_25(){
		t254.split(8);
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testSplit1_25(){
		EditTree temp = t254.split(4);
		assertEquals("foot",t254.toString());
		assertEquals("ball",temp.toString());
		assertTrue(t254.isHeightBalanced());
		assertTrue(temp.isHeightBalanced());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testGet1_25(){
		assertEquals('3', t257.get(6));
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testGet2_25(){
		assertEquals('a', t252.get(0));
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testCheckRanks2_25(){
		assertTrue(t252.checkRanks());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testCheckRanks7_25(){
		assertTrue(t257.checkRanks());
		points += 1;
	}
	
	@Test(timeout=1000)
	public void testCheckRanks8_25(){
		assertFalse(t258.checkRanks());
		points += 1;
	}
}