import java.io.*;
/**
 *
 * @author  David Matuszek
 * @version 1
 */
public class AnimalsGame {
    private AnimalsGui frame;
    private final boolean YES = true;

    private String initialMessage = "Welcome to the Animals game. To play,\n" +
    "think of an animal, then click Yes.";
    private String guessMessage = "I know! Is your animal ";
    private String bragMessage  = "See? People should work, computers should think!";
    private String again = "\nWould you like to play again?";
    private String whatAnimal = "I give up. What animal are you thinking of?";
    private String getQuestion = "What question should I ask to distinguish ";
    private String getAnswer = "What is the correct answer for ";
    private String thanks = "Thanks! I'll remember that!";


    /**
     * Creates and plays the <i>Animals!</i> game.
     * 
     * @param args Unused.
     */
    public static void main(String args[]) {
        AnimalsGame game = new AnimalsGame();
        game.doStuff();
    }

    /**
     * Plays the <i>Animals!</i> game.
     */
    void doStuff() {
        frame = new AnimalsGui();
        frame.setVisible(true);

        BinaryTree tree = createInitialDecisionTree();
        play(tree);
    }

    private BinaryTree createInitialDecisionTree() {
        BinaryTree tree;
        tree = new BinaryTree("Does it live in the water?",
                              new BinaryTree("a frog"),
                              new BinaryTree("a horse"));
        return tree;
    }

    private void play(BinaryTree tree) {
        boolean answer;
        boolean playing;
        String guessedAnimal;
        String newAnimal;
        String newQuestion;
        
        playing = frame.yesOrNo(initialMessage, "Quit");
        while (playing) {
            BinaryTree here = tree;
            // Walk tree
            here = walkDownToALeaf(here);
            // Reached a leaf, so make a guess
            guessedAnimal = (String)here.getValue();
            answer = frame.yesOrNo(guessMessage + guessedAnimal + "?");
            if (answer == YES) { // guessed correctly, so brag
                playing = frame.yesOrNo(bragMessage + again, "Quit");
            }
            else { // guessed incorrectly, so get new animal
                newAnimal = frame.getText(whatAnimal, false);
                newAnimal = addDeterminer(newAnimal);
                newQuestion = frame.getText(getQuestion + newAnimal +
                                            " from " + guessedAnimal + "?",
                                            true);
                answer = frame.yesOrNo(getAnswer + newAnimal + "?");

                // Build new node
                here.setValue(newQuestion);
                if (answer == YES) {
                    here.setLeftChild(new BinaryTree(newAnimal));
                    here.setRightChild(new BinaryTree(guessedAnimal));
                }
                else {
                    here.setLeftChild(new BinaryTree(guessedAnimal));
                    here.setRightChild(new BinaryTree(newAnimal));
                }
                playing = frame.yesOrNo(thanks + again, "Quit");
            }
        }
        System.exit(0);
    }

    private BinaryTree walkDownToALeaf(BinaryTree here) {
        boolean answer;
        while (! here.isLeaf()) {
            answer = frame.yesOrNo((String)here.getValue());
            if (answer == YES) here = here.getLeftChild();
            else here = here.getRightChild();
        }
        return here;
    }

    /**
     * Removes an initial "a ", "an ", or "the " from the String, if present.
     *
     * @param animal the string to be edited.
     * @return the string without an initial determiner.
     */
    public static String removeDeterminer(String animal) {
        if (animal.startsWith("A ") || animal.startsWith("a ")) {
            return animal.substring(2);
        }
        if (animal.startsWith("An ") || animal.startsWith("an ")) {
            return animal.substring(3);
        }
        if (animal.startsWith("The ") || animal.startsWith("the ")) {
            return animal.substring(4);
        }
        else
            return animal;
    }

    /**
     * Adds an initial "a " or "an " to the String, after first
     * ensuring that it doesn't already begin with one.
     *
     * @param animal the string to be edited.
     * @return the string with an initial determiner.
     */
    public static String addDeterminer(String animal) {
        animal = removeDeterminer(animal);
        if ("aeiouAEIOU".indexOf(animal.charAt(0)) >= 0)
            return "an " + animal;
        else
            return "a " + animal;
    }
}
