import java.util.Scanner;
import java.util.List;

/**
 * A program to show the various ways of messing with private lists.
 *
 * @author Mark Young (A00000000)
 */
public class TestPrivateList {

    public static void main(String[] args) {
        PrivateList one, two, three;
        List<String> unsafe, copy, safe;

        // introduce yourself
        System.out.println("\n"
                + "A PrivateList is a list of Strings that refuses to add "
                + "nulls or words starting with F.\n");
        pause();

        // Using an unsafe getter
        System.out.println("Let's make a PrivateList");
        one = makeList();
        System.out.println("\tone == " + one);
        pause();
        System.out.println("Let unsafe = one.getWordsUnsafe()");
        unsafe = one.getWordsUnsafe();
        System.out.println("Messing with unsafe");
        messWith(unsafe);
        System.out.println("After messing with it, unsafe == " + unsafe);
        System.out.println("After messing with unsafe, one == " + one);
        pause();

        // Using a copy getter
        System.out.println("Let's make a PrivateList");
        two = makeList();
        System.out.println("\ttwo == " + two);
        pause();
        System.out.println("Let copy = two.getWordsCopy()");
        copy = two.getWordsCopy();
        System.out.println("Messing with copy");
        messWith(copy);
        System.out.println("After messing with it, copy == " + copy);
        System.out.println("After messing with copy, two == " + two);
        pause();

        // Using an immutableList getter
        System.out.println("Let's make a PrivateList");
        three = makeList();
        System.out.println("\tthree == " + three);
        pause();
        System.out.println("Let safe = three.getWordsSafe()");
        safe = three.getWordsSafe();
        System.out.println("Messing with safe");
        messWith(safe);
        System.out.println("After messing with it, safe == " + safe);
        System.out.println("After messing with safe, three == " + three);
        pause();

        // Updating the list behind the view
        System.out.println("As a bonus, let's add to three...");
        three.addWord("extended");
        System.out.println("\tthree == " + three);
        pause();
        System.out.println("...and safe is ALSO updated...");
        System.out.println("\tsafe == " + safe);
        System.out.println("...because it's a VIEW of three!");
        pause();
    }

    /**
     * Make a PrivateList with several elements, reporting whether each item is added.
     *
     * @return a PrivateList containing multiple words.
     */
    private static PrivateList makeList() {
        PrivateList result = new PrivateList();

        String[] words = {"Here", "is", null, "my", "fecking", "list"};
        for (String w : words) {
            if (result.addWord(w)) {
                System.out.println(" -- added " + w);
            } else {
                System.out.println(" -- FAILED to add " + w);
            }
        }

        return result;
    }


    /**
     * Try to add/change/delete words in a PrivateList. With proper
     * encapsulation, none of these operations should modify the PrivateList
     * object.
     *
     * @param list the list of words from the PrivateList.
     */
    private static void messWith(List<String> list) {
        try {
            if (list.add("for")) {
                System.out.println("\tAdded for");
            } else {
                System.out.println("\tFailed to add for");
            }
        } catch (UnsupportedOperationException e) {
            System.out.println("\tadd not supported");
        }
        try {
            if (list.add(null)) {
                System.out.println("\tAdded null");
            } else {
                System.out.println("Failed to add null");
            }
        } catch (UnsupportedOperationException e) {
            System.out.println("\tadd not supported");
        }
        try {
            String item = list.remove(0);
            if (item != null) {
                System.out.println("\tRemoved " + item + " from position 0");
            } else {
                System.out.println("Failed to remove from position 0");
            }
        } catch (UnsupportedOperationException e) {
            System.out.println("\tremove not supported");
        }
        try {
            String item = list.set(0, "CHANGED");
            System.out.println("\tChanged position 0 from " + item 
                    + " to CHANGED");
        } catch (UnsupportedOperationException e) {
            System.out.println("\tset not supported");
        }
        System.out.println();
    }

    private static final Scanner kbd = new Scanner(System.in);

    /**
     * Prompt the user and wait for them to press enter.
     */
    private static void pause() {
        System.out.println();
        System.out.print("...press enter...");
        kbd.nextLine();
        System.out.println();
    }

}
