package a02;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

/**
 * A program to test the Domino class.
 * 
 * @author Mark Young (A00000000)
 */
public class A02 {

    public static final Scanner KBD = new Scanner(System.in);
    private static final int MAX_PIPS = 12;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // Create bone yard
        List<Domino> bones = generateDominoes(MAX_PIPS);

        // print intro
        printIntroduction();
        
        // show the natural sort
        printTitle("Natural Sort");
        Collections.shuffle(bones);
        Collections.sort(bones);
        printBones(bones);
        pause();

        // show the sum sort
        printTitle("Sorted by Sum");
        Collections.shuffle(bones);
        bones.sort(Domino.BY_SUM);
        printBones(bones);
        pause();

        // show just ones with a 5
        printTitle("Just the Fives");
        List<Domino> just5s = new ArrayList<>();
        for (Domino dom : bones) {
            if (dom.has(5)) {
                just5s.add(dom);
            }
        }
        printBones(just5s);
        pause();

        // show just ones that are doubles
        printTitle("Just the Doubles");
        List<Domino> justDoubles = new ArrayList<>();
        for (Domino dom : bones) {
            if (dom.isDouble()) {
                justDoubles.add(dom);
            }
        }
        printBones(justDoubles);
        pause();

        // show just the double 3
        printTitle("Just the Double Three");
        List<Domino> justDouble3 = new ArrayList<>();
        for (Domino dom : bones) {
            if (dom.isDouble(3)) {
                justDouble3.add(dom);
            }
        }
        printBones(justDouble3);
        pause();

        // show just those that sum to 7
        printTitle("Just Those That Sum to Seven");
        List<Domino> justSumTo7 = new ArrayList<>();
        for (Domino dom : bones) {
            if (dom.getSum() == 7) {
                justSumTo7.add(dom);
            }
        }
        printBones(justSumTo7);
        pause();
        
        // high and low values of the sum-to-7 dominoes
        printTitle("High, Low, and Other Values");
        for (Domino dom : justSumTo7) {
            try {
                System.out.println("\t" + dom + ".getHigh()   == "
                        + dom.getHigh());
                System.out.println("\t" + dom + ".getLow()    == "
                        + dom.getLow());
                System.out.println("\t" + dom + ".getOther(2) == "
                        + dom.getOther(2));
            } catch (IllegalArgumentException iae) {
                System.out.println("Refused: " + dom + " has no "
                        + iae.getMessage());
            }
        }
        pause();

        // error processing
        printTitle("Dealing with Unusual Situations");
        Domino bad = null;
        try {
            bad = new Domino(-1, 5);
            System.out.println("Bad domino: " + bad);
        } catch (IllegalArgumentException iae) {
            System.out.println("Refused: new Domino(-1, 5) because "
                    + iae.getMessage());
        }
        try {
            bad = new Domino(1, -5);
            System.out.println("Bad domino: " + bad);
        } catch (IllegalArgumentException iae) {
            System.out.println("Refused: new Domino(1, -5) because "
                    + iae.getMessage());
        }
        try {
            bad = new Domino(100, 5);
            System.out.println("Bad domino: " + bad);
        } catch (IllegalArgumentException iae) {
            System.out.println("Refused: new Domino(100, 5) because "
                    + iae.getMessage());
        }
        try {
            bad = new Domino(7, 105);
            System.out.println("Bad domino: " + bad);
        } catch (IllegalArgumentException iae) {
            System.out.println("Refused: new Domino(7, 105) because "
                    + iae.getMessage());
        }
        bad = new Domino(1, 5);
        try {
            System.out.println(bad + ".has(-1) == " + bad.has(-1));
        } catch (IllegalArgumentException iae) {
            System.out.println("Refused: " + bad + ".has(-1) because "
                    + iae.getMessage());
        }
        try {
            System.out.println(bad + ".isDouble(-1) == " + bad.isDouble(-1));
        } catch (IllegalArgumentException iae) {
            System.out.println("Refused: " + bad + ".isDouble(-1) because "
                    + iae.getMessage());
        }
    }

    /**
     * Print the introduction for this program.
     */
    private static void printIntroduction() {
        printTitle("Dominoes", "=");
        System.out.println("This program generates, sorts, "
                + "and prints dominoes.\n\n"
                + "Program by Mark Young (A00000000)\n"
                + "Domino class by " + Domino.getAuthor());
        System.out.println();
    }
    
    /**
     * Print out the given text as a title, underlined with the given character.
     * 
     * @param text the text of the title
     * @param line the character to use to underline the title
     */
    private static void printTitle(String text, String line) {
        System.out.println(text);
        for (int i = 0; i < text.length(); ++i) {
            System.out.print(line);
        }
        System.out.println("\n");
    }

    /**
     * Print out the given text as a title, underlined with a hyphen.
     * 
     * @param text the text of the title
     */
    private static void printTitle(String text) {
        printTitle(text, "-");
    }
        
    /**
     * Create a list (set) of dominoes with the given maximum number of pips. A
     * set of dominoes has one domino with each pair of numbers from the set 0
     * .. maxPips. If maxPips is less than zero, the empty list will be
     * returned.
     *
     * @param maxPips the largest number of pips on one side of any domino.
     * @return a list of all the dominoes in the requested set.
     */
    private static List<Domino> generateDominoes(int maxPips) {
        List<Domino> result = new ArrayList<>();

        for (int high = 0; high <= maxPips; ++high) {
            for (int low = 0; low <= high; ++low) {
                result.add(new Domino(high, low));
            }
        }

        return result;
    }

    /**
     * Maximum number of dominoes per printed line
     */
    private static final int MAX_PER_LINE = 7;

    /**
     * Print out the dominoes in the given list, MAX_PER_LINE per line.
     *
     * @param bones the list of dominoes to print.
     */
    private static void printBones(List<Domino> bones) {
        int onThisLine = 0;
        for (Domino dom : bones) {
            if (onThisLine == MAX_PER_LINE) {
                System.out.println();
                onThisLine = 0;
            }
            System.out.print("\t" + dom);
            ++onThisLine;
        }
        System.out.println();
    }

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

}
