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 intialize 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 {
		setUpInstructors();
		setUp11();
		setUp12();
		setUp13();
		setUp14();
		setUp15();
		setUp16();
		setUp21();
		setUp22();
		setUp23();
		setUp24();
		setUp25();
		setUp26();
	}

	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 {

	}

	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 testAddChar_14() {
		EditTree addTree = new EditTree();
		addTree.add('j');
		assertEquals("j", addTree.toString());
		points++;
	}

	@Test(timeout = 1000)
	public void testAddShortString_14() {
		EditTree addTree = new EditTree();
		for (int i = 0; i < s1.length(); i++) {
			addTree.add(s1.charAt(i));
		}
		assertEquals(s1, addTree.toString());
		points++;
	}

	@Test(timeout = 1000)
	public void testAddModShortString_14() {
		EditTree addTree = new EditTree();
		for (int i = 0; i < s2.length(); i++) {
			addTree.add(s2.charAt(i));
		}
		assertEquals(s2, addTree.toString());
		points++;
	}

	@Test(expected = IndexOutOfBoundsException.class)
	public void testAddPosOutofBoundsNullRoot_14() {
		EditTree addTree = new EditTree();
		addTree.add('j', 1);
		points++;
	}

	@Test(expected = IndexOutOfBoundsException.class)
	public void testAddPosOutofBoundsWithString_14() {
		EditTree addTree = new EditTree();
		for (int i = 0; i < s1.length(); i++) {
			addTree.add(s1.charAt(i));
		}
		addTree.add('j', 20);
		points++;
	}

	@Test(expected = IndexOutOfBoundsException.class)
	public void testAddPosOutofBoundsNegative_14() {
		EditTree addTree = new EditTree();
		for (int i = 0; i < s1.length(); i++) {
			addTree.add(s1.charAt(i));
		}
		addTree.add('j', -1);
		points++;
	}

	@Test(timeout = 1000)
	public void testAddChartoEnd_14() {
		EditTree addTree = new EditTree();
		for (int i = 0; i < s1.length(); i++) {
			addTree.add(s1.charAt(i));
		}
		addTree.add('s', 12);
		assertEquals(s1 + "s", addTree.toString());
		points++;
	}

	@Test(timeout = 1000)
	public void testAddChartoBeginning_14() {
		EditTree addTree = new EditTree();
		for (int i = 0; i < s1.length(); i++) {
			addTree.add(s1.charAt(i));
		}
		addTree.add(' ', 0);
		assertEquals(" " + s1, addTree.toString());
		points++;
	}

	@Test(timeout = 1000)
	public void testAddChartoMiddle_14() {
		EditTree addTree = new EditTree();
		for (int i = 0; i < s1.length(); i++) {
			addTree.add(s1.charAt(i));
		}
		addTree.add('.', 6);
		assertEquals("short. string", addTree.toString());
		points++;
	}

	// String 1
	@Test(timeout = 1000)
	public void testStringOneHeightSizeAddAndDelete_14() {
		t140 = new EditTree(s1);
		assertTrue(t140.height() <= 4);
		assertEquals(12, t140.size());
		t140.add('z', 2);
		assertEquals(13, t140.size());
		t140.delete(2);
		assertEquals(12, t140.size());
	}

	// Null
	@Test(timeout = 1000)
	public void testNullTreeHeightSize_14() {
		t140 = new EditTree();
		assertEquals(-1, t140.height());
		assertEquals(0, t140.size());
		points++;
	}

	// Add one character
	@Test(timeout = 1000)
	public void testAddToNull_14() {
		t140 = new EditTree();
		t140.add('c');
		assertEquals(1, t140.size());
		assertEquals(0, t140.height());
		assertEquals(0, t140.getRoot().rank);
		t140.add('h');
		assertEquals(1, t140.getRoot().rank);
		points++;
	}

	// Find a single character string
	@Test(timeout = 1000)
	public void testFindOneCharStringInOneCharTree_14() {
		t140 = new EditTree("a");
		assertFalse(t140.find("a") == -1);
		points++;
	}

	// Deletes root, checks root rank again, checks if deleted node is in
	// the tree
	@Test(timeout = 1000)
	public void testDeleteRankandGetRoot_14() {
		t140 = new EditTree("a");
		t140.delete(0);
		assertEquals(0, t140.getRoot().rank);
		assertTrue(t140.find("c") == -1);
		points++;
	}

	// Deletes a node, checks for height
	@Test(timeout = 1000)
	public void testDeleteAndCheckHeight_14() {
		t140 = new EditTree(s1);
		t140.delete(0);
		assertTrue(t140.height() <= 3);
		points++;
	}

	// Add to end of tree by looping, check height
	@Test(timeout = 1000)
	public void testAddAndCheckHeight_14() {
		t140 = new EditTree();
		for (int i = 0; i < s1.length(); i++) {
			t140.add(s1.charAt(i));
		}
		assertTrue(t140.height() <= 4);
		points++;
	}

	// Find s1
	@Test(timeout = 1000)
	public void testFindS1InS1Tree_14() {
		t140 = new EditTree(s1);
		assertFalse(t140.find(s1) == -1);
		points++;
	}

	// Concatenate 2 null trees
	@Test(timeout = 1000)
	public void testConcatNullTrees_14() {
		t140 = new EditTree();
		t141 = new EditTree();
		t140.concatenate(t141);
		assertEquals(0, t140.size());
		assertEquals(-1, t140.height());
		points++;
	}

	// Concatenate a null tree with a tree containing 1 node (Also tests
	// find)
	@Test(timeout = 1000)
	public void testConcatNullAndSingleAndCheck_14() {
		t140 = new EditTree();
		t141 = new EditTree('a');
		t140.concatenate(t141);
		assertEquals(1, t140.size());
		assertEquals(0, t140.height());
		assertFalse(t140.find("a") == -1);
		assertTrue(t140.find("a") == -1);
		points++;
	}

	// Concatenate a null tree with a tree containing many nodes (Also tests
	// find)
	@Test(timeout = 1000)
	public void testConcatNullAndManyAndCheck_14() {
		t140 = new EditTree();
		t141 = new EditTree(s1);
		t140.concatenate(t141);
		assertTrue(t140.height() <= 4);
		assertEquals(12, t140.size());
		assertEquals(0, t141.size());
		assertFalse(t140.find(s1) == -1);
		assertTrue(t140.find(s1) == -1);
		points++;
	}

	// Concatenate 2 trees containing many nodes
	@Test(timeout = 1000)
	public void testConcatMediumAndCheck_14() {
		t140 = new EditTree(s1);
		t141 = new EditTree(s2);
		t140.concatenate(t141);
		int newSize = s1.length() + s2.length();
		assertEquals(newSize, t140.size());
		assertTrue(t140.height() <= 5);
		assertFalse(t140.find(s1) == -1);
		assertFalse(t140.find(s2) == -1);
		points++;
	}

	// Mega-concatenation
	@Test(timeout = 1000)
	public void testConcatBig_14() {
		t142 = new EditTree(s4);
		t143 = new EditTree(s5);
		t143.concatenate(t143);
		assertTrue(t143.isHeightBalanced());
		points++;
	}

	// Split a larger tree
	@Test(timeout = 1000)
	public void testSplitLargeTree_14() {
		t140 = new EditTree(s1);
		t141 = t140.split(s1.length() - 1);
		assertTrue(t140.toString().equals(s1));
		assertTrue(t141.toString().equals(s2));
		assertTrue(t140.isHeightBalanced() && t141.isHeightBalanced());
		points++;
	}

	// Split a small tree
	@Test(timeout = 1000)
	public void testSplitSmallTree_14() {
		t140 = new EditTree("abc");
		t141 = t140.split(1);
		assertEquals(1, t140.height());
		assertEquals(0, t141.height());
		assertTrue(t140.toString().equals("ba"));
		assertTrue(t141.toString().equals("c"));
		points++;
	}

	// Split slippery
	@Test(timeout = 1000)
	public void testSplitSlippery_14() {
		t140 = new EditTree("SLIPPERY");
		t141 = t140.split(0);
		assertTrue(t140.toString().equals("S"));
		assertTrue(t141.toString().equals("LIPPERY"));
		assertTrue(t141.height() <= 3);
		assertTrue(t141.isHeightBalanced());
		points++;
	}

	// find a string at a position
	@Test(timeout = 1000)
	public void testSplitSlipperyAndFindsSubstrings_14() {
		assertTrue(t141.find("LIP", 0) == 0);
		assertTrue(t141.find("S", 0) == -1);
		assertTrue(t141.find("P", 0) == 2);
		points++;
	}

	// check ranks for various trees
	@Test(timeout = 1000)
	public void testRankCheckS3_14() {
		t143 = new EditTree(s3);
		assertTrue(t143.checkRanks());
		points++;
	}

	@Test(timeout = 1000)
	public void testRankCheckS4_14() {
		t144 = new EditTree(s4);
		assertTrue(t144.checkRanks());
		points++;
	}

	@Test(timeout = 1000)
	public void testRankCheckWithAddS3_14() {
		t143 = new EditTree(s3);
		assertTrue(t143.checkRanks());
		t143.add('c'); // Add one char to t143
		assertTrue(t143.checkRanks());
		points++;
	}

	@Test(timeout = 1000)
	public void testRankCheckWithAddS4_14() {
		t144 = new EditTree(s4);
		assertTrue(t144.checkRanks());
		for (int i = 0; i < 10; i++)
			// Add many to t144
			t144.add('s');
		assertTrue(t144.checkRanks());
		points++;
	}

	// getsTest
	@Test(timeout = 1000)
	public void testGets_14() {
		t145 = new EditTree(s1);
		assertEquals('s', t145.get(0));
		t146 = new EditTree(s2);
		assertEquals('a', t146.get(0));
		t147 = new EditTree(s3);
		assertEquals('T', t147.get(0));
		points++;
	}
}