import junit.framework.TestCase;

/*
 * Created on Sep 29, 2007
 */

public class ComputerPlayerTest extends TestCase {
    TicTacToeBoard board;
    ComputerPlayer computerPlayer = new ComputerPlayer();
    char[][] array;
    
    public ComputerPlayerTest(String arg0) {
        super(arg0);
    }

    protected void setUp() throws Exception {
        super.setUp();
        board = new TicTacToeBoard();
        array = board.board;
    }

    public final void testMakeCenterMove() {
        beforeAndAfterMove("         ","    X    ");
        beforeAndAfterMove("xo   xoxo","xo  xxoxo");
        beforeAndAfterMove("xxoo xxoo","xxooxxxoo");
    }
    
    public final void testMakeCornerMove() {
        // Center and all other corners taken (note: illegal board state!)
        beforeAndAfterMove("  x x x x", "x x x x x");
        beforeAndAfterMove("x   x x x", "x x x x x");
        beforeAndAfterMove("x x x x  ", "x x x x x");
        beforeAndAfterMove("x x x   x", "x x x x x");
        // Corner move is all that's left
        beforeAndAfterMove(" oxoxxoxo", "xoxoxxoxo");
        beforeAndAfterMove("oo xxooxx", "ooxxxooxx");
        beforeAndAfterMove("oxoxxoxo ", "oxoxxoxox");
        beforeAndAfterMove("xxooxxxoo", "xxooxxxoo");
        // Everything but center is available
        String[] cornersTaken = new String[] { "x   o    ", "  x o    ",
                                               "    o x  ", "    o   x" };
        beforeAndAfterMove("    o    ", cornersTaken);
    }
    
//    public final void testOPTIONALmakeWinningMove() {
//        beforeAndAfterMove("oxo o x x", "oxo o xxx");
//        beforeAndAfterMove("xx   oo  ", "xxx  oo  ");
//        beforeAndAfterMove("o  xx  o ", "o  xxx o ");
//    }
//    
//    public final void testOPTIONALmakeForcedMove() {
//        beforeAndAfterMove("o o x   x", "oxo x   x");
//        beforeAndAfterMove("xox o    ", "xox o  x ");
//        beforeAndAfterMove("xxo     o", "xxo     o");
//    }
    
    public final void testMakeEdgeMove() {
        beforeAndAfterMove("x o o o x", new String[] { "xxo o o x", "x o oxo x",
                                                       "x o o oxx", "x oxo o x" });
    }

    private void setBoard(String xxx) {
        xxx = xxx.toUpperCase();
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                array[i][j] = Character.toUpperCase(xxx.charAt(3 * i + j));
            }
        }
    }
    
    private void assertBoardIs(String xxx) {
        assertEquals(xxx.toUpperCase(), toString(board).toUpperCase());
    }
    
    /**
     * Returns the tic-tac-toe <code>board</code> as a nine-character string
     * consisting of 'X', 'O', and blank characters.
     * 
     * @param board The board to represent as a string.
     * @return The string representation of the board.
     */
    String toString(TicTacToeBoard board) {
        String s;
        s = "" + board.get(1, 1)  + board.get(1, 2) + board.get(1, 3)
               + board.get(2, 1)  + board.get(2, 2) + board.get(2, 3)
               + board.get(3, 1)  + board.get(3, 2) + board.get(3, 3);
        return s.toUpperCase();
    }
    
    /**
     * Checks whether the computer makes the correct move.
     * @param before The board before the move.
     * @param after The board after the move.
     */
    private void beforeAndAfterMove(String before, String after) {
        setBoard(before);
        computerPlayer.makeMove(board);
        assertBoardIs(after);
    }
    
    /**
     * Checks whether the computer makes some correct move.
     * @param before The board before the move.
     * @param validResults Valid board positions after the move.
     */
    private void beforeAndAfterMove(String before, String[] validResults) {
        setBoard(before.toUpperCase());
        computerPlayer.makeMove(board);
        String actualResult = toString(board);

        boolean ok = false;
        for (int i = 0; i < validResults.length; i++) {
            validResults[i] = validResults[i].toUpperCase();
            ok = ok || actualResult.equals(validResults[i]);
        }
        assertTrue("Invalid result [" + actualResult + "]", ok);
    }
}
