package anabalica.github.io.meowletters;

import junit.framework.*;

import java.util.ArrayList;

import anabalica.github.io.meowletters.letters.Letter;
import anabalica.github.io.meowletters.letters.LetterChain;

/**
 * Test LetterChain class
 *
 * @author Ana Balica
 */
public class LetterChainTest extends TestCase {
    protected LetterChain letterChain = new LetterChain();
    protected ArrayList<Letter> chain = new ArrayList<Letter>();

    public void testIsValid() {
        // Test empty chain
        assertTrue(letterChain.isValid());

        // Test chain with a single element
        chain.add(new Letter("K"));
        letterChain.setChain(chain);
        assertTrue(letterChain.isValid());

        // Test a very long chain
        chain.clear();
        String longChain = "QWFPGJLUYARSTDHNEZXCVBKMWQFPGJLRSTDHNE";
        for (int i = 0; i < longChain.length(); i++) {
            chain.add(new Letter(Character.toString(longChain.charAt(i))));
        }
        assertFalse(letterChain.isValid());

        // Test two consecutive elements
        chain.clear();
        chain.add(new Letter("G"));
        chain.add(new Letter("H"));
        assertTrue(letterChain.isValid());

        // Test three non consecutive elements
        chain.add(new Letter("B"));
        assertFalse(letterChain.isValid());

        // Test circular chain elements
        chain.clear();
        chain.add(new Letter("Z"));
        chain.add(new Letter("A"));
        assertFalse(letterChain.isValid());
    }

    public void testAdd() {
        // Test adding one element to the chain
        letterChain.add(new Letter("A"));
        assertFalse(letterChain.isEmpty());
        assertEquals(letterChain.size(), 1);
        assertEquals(letterChain.get(0), new Letter("A"));

        // Test adding another element
        letterChain.add(new Letter("B"));
        assertEquals(letterChain.size(), 2);
        assertEquals(letterChain.get(1), new Letter("B"));
    }

    public void testRemove() {
        // Test removing from empty chain
        try {
            letterChain.remove(new Letter("P"));
            fail("Exception not thrown");
        } catch (IllegalArgumentException e) {
            assertEquals(e.getMessage(), "Letter not in chain.");
        }

        letterChain.add(new Letter("T"));
        letterChain.add(new Letter("Q"));
        letterChain.add(new Letter("W"));

        // Test removing non existing element
        try {
            letterChain.remove(new Letter("P"));
            fail("Exception not thrown");
        } catch (IllegalArgumentException e) {
            assertEquals(e.getMessage(), "Letter not in chain.");
        }

        // Test removing one element
        letterChain.remove(new Letter("W"));
        assertEquals(letterChain.size(), 2);
        assertEquals(letterChain.get(0), new Letter("T"));
        assertEquals(letterChain.get(1), new Letter("Q"));

        // Test removing middle element
        letterChain.add(new Letter("C"));
        letterChain.add(new Letter("Z"));
        letterChain.add(new Letter("Y"));
        letterChain.remove(new Letter("Z"));
        assertEquals(letterChain.size(), 3);
        assertEquals(letterChain.get(0), new Letter("T"));
        assertEquals(letterChain.get(1), new Letter("Q"));
        assertEquals(letterChain.get(2), new Letter("C"));

        // Test removing the first element
        letterChain.remove(new Letter("T"));
        assertTrue(letterChain.isEmpty());
    }

    public void testSort() {
        LetterChain letterChain = new LetterChain();
        letterChain.sort();
        Letter letterZ = new Letter("Z");
        Letter letterG = new Letter("G");
        Letter letterF = new Letter("F");
        letterChain.add(letterZ);
        letterChain.add(letterG);
        letterChain.add(letterF);
        letterChain.sort();

        assertEquals(letterChain.get(0), letterF);
        assertEquals(letterChain.get(1), letterG);
        assertEquals(letterChain.get(2), letterZ);
    }

    public void testGenerateRandomChain() {
        // Test a chain of zero length
        LetterChain letterChain1 = LetterChain.generateRandomChain(0);
        assertEquals(letterChain1.size(), 0);
        // Test to generate a chain of a positive number length
        LetterChain letterChain2 = LetterChain.generateRandomChain(5);
        assertEquals(letterChain2.size(), 5);
        // Test to generate a chain of a negative number length
        try {
            LetterChain.generateRandomChain(-1);
            fail("Exception not thrown");
        } catch (IllegalArgumentException e) {
            assertEquals(e.getMessage(), "The requested chain length can't be negative.");
        }
    }

    public void testGenerateValidChain() {
        // Test a valid letter chain of 15
        LetterChain letterChain = LetterChain.generateValidChain(15);
        assertEquals(letterChain.size(), 15);
        for (int i = 1; i < letterChain.size(); i++) {
            assertEquals(letterChain.get(i), letterChain.get(i-1).next());
        }

        // Test to generate a chain of a negative number length
        try {
            LetterChain.generateValidChain(-1);
            fail("Exception not thrown");
        } catch (IllegalArgumentException e) {
            assertEquals(e.getMessage(), "The requested chain length can't be negative.");
        }

        // Test to generate a chain of length larger than the number of letters in alphabet
        try {
            LetterChain.generateValidChain(27);
            fail("Exception not thrown");
        } catch (IllegalArgumentException e) {
            assertEquals(e.getMessage(), "The requested chain length exceeds the alphabet length.");
        }
    }
}

@@ -205,16 +205,75 @@
 erChain;
+%0Aimport anabalica.github.io.meowletters.letters.LetterGrid;
 %0A%0A/**%0A *
@@ -1561,32 +1561,828 @@
 alid());%0A    %7D%0A%0A
+    public void testIsFinal() %7B%0A        Letter grid%5B%5D%5B%5D = %7B%0A                %7Bnew Letter(%22Z%22), new Letter(%22D%22), null%7D,%0A                %7Bnew Letter(%22D%22), null, new Letter(%22F%22)%7D,%0A                %7Bnew Letter(%22E%22), null, new Letter((%22Z%22))%7D%0A        %7D;%0A        LetterGrid letterGrid = new LetterGrid(grid);%0A        LetterChain letterChain = new LetterChain();%0A        assertFalse(letterChain.isFinal(letterGrid));%0A        letterChain.add(new Letter(%22Z%22));%0A        assertTrue(letterChain.isFinal(letterGrid));%0A        letterChain.add(new Letter(%22D%22));%0A        assertFalse(letterChain.isFinal(letterGrid));%0A        letterChain.add(new Letter(%22E%22));%0A        assertFalse(letterChain.isFinal(letterGrid));%0A        letterChain.add(new Letter(%22F%22));%0A        assertTrue(letterChain.isFinal(letterGrid));%0A    %7D%0A%0A
     public void 

add unittest to LetterChain.isFinal()