import java.util.NoSuchElementException;


/**
 * This is a driver class for testing a K_RecList implementation (a simple
 * recursive list that does not implement the full Java List interface).
 * 
 * @Author Alyce Brady
 * @version Oct 1, 2025
 */
public class K_RecListTester
{

    /**
     * Runs a series of tests.
     */
    public static void main(String[] args)
    {
        testSize();
        testHeadTail();
        testHeadOfEmpty();
        testTailOfEmpty();
        System.out.println("\nTests complete.");
    }


    /**
     * A helper function that creates a list containing all of the letters
     * in the alphabet.  Letters are added to the beginning of the list,
     * starting with A.  Items should end up in reverse alphabetical order.
     * 
     * @return list of letters
     */
    public static K_RecList<String> buildTestList()
    {
        String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        K_RecList<String> stringList = new K_RecList<>();

        for (int i = 0; i< alphabet.length(); i++)
        {
            String letterAsString = alphabet.substring(i, i+1);
            stringList = new K_RecList<>(letterAsString, stringList);
        }
        return stringList;
    }

    /**
     * A helper function that generate a string representing a recursive
     * linked list.  The elements in the list are space separated rather
     * than comma separated.
     * 
     * @return a string representing the elements in the list
     */
    public static String listToString(K_RecList<String> theList)
    {
        return "[ " + theList.toString() + "]";
    }


    /**
     * Run tests to see if size() is calculated correctly by the K_RecList
     * class.
     */
    public static void testSize()
    {
        K_RecList<String> stringList = new K_RecList<>();
        System.out.println("\nTesting isEmpty and size methods...");
        System.out.println("Initial size of list: Expected 0; Actual "
                + stringList.size());

        stringList = buildTestList();
        System.out.println("After all elements are added: "
                + listToString(stringList));

        System.out.println("Size: Expected 26; Actual: "
                + stringList.size());
        stringList = stringList.tail();
        System.out.println("Size of tail: Expected 25; Actual "
                + stringList.size());

        while ( ! stringList.isEmpty() )
            stringList = stringList.tail();
        System.out.println("Size of list after emptying: Expected 0; Actual "
                + stringList.size());
    }

    /**
     * Run tests to see if head and tail methods are implemented correctly
     * by the K_RecList class.
     */
    public static void testHeadTail()
    {
        System.out.println("\nTesting effect of head and tail methods...");
        K_RecList<String> stringList = buildTestList();
        System.out.println("Initial list: " + listToString(stringList));

        String elt = stringList.head();
        System.out.println("First element: Expected Z; Actual " + elt);

        stringList = stringList.tail();
        elt = stringList.head();
        System.out.println("First element of tail: Expected Y; Actual " + elt);
        System.out.println("Tail of tail: " + listToString(stringList.tail()));
    }

    /**
     * Test to see if the head of an empty list is null.  An alternative
     * would be to throw an exception when asking for the head of an empty list.
     */
    public static void testHeadOfEmpty()
    {
        K_RecList<String> stringList = new K_RecList<>();
        String result = stringList.head();
        System.out.println("Head of empty list: Expected null; Actual " + 
            (result == null ? "null" : "not null"));
    }

    /**
     * Test to see if the tail of an empty list is an empty list.  An
     * alternative would be to throw an exception when asking for the tail
     * of an empty list.
     */
    public static void testTailOfEmpty()
    {
        K_RecList<String> stringList = new K_RecList<>();
        K_RecList<String> tail = stringList.tail();

        try
        {
            tail = stringList.tail();
        }
        catch(Exception e)
        {
            System.out.println("   Caught: " + e);
        }

        System.out.println("Tail of empty list: Expected: empty; Actual " + 
            (tail.isEmpty() ? "empty" : "not empty"));
    }

}    


