from unittest import TestCase, main

from tic_tac_toe.board import Mark, BOARD_SIZE, MARK_COUNT, Board
from tic_tac_toe.ai import ai


def create_board(*lines):
    marks = [None] * MARK_COUNT
    for y, line in enumerate(lines):
        for x, character in enumerate(line):
            try:
                marks[y * BOARD_SIZE + x] = Mark(character)
            except ValueError:
                pass
    return Board(marks)


class TestAI(TestCase):
    def test_first_move(self):
        board = create_board(
            '012',
            '345',
            '678',
        )
        self.assertEqual(
            ai.choose_move_and_description(board),
            (4, 'The computer claims the center.'),
        )

    def test_second_move_versus_corner(self):
        board = create_board(
            '012',
            '3O5',
            'X78',
        )
        self.assertEqual(
            ai.choose_move_and_description(board),
            (2, 'The computer plays in the corner.'),
        )

    def test_third_move_versus_corner_and_adjacent_side(self):
        board = create_board(
            '01O',
            '3O5',
            'XX8',
        )
        self.assertEqual(
            ai.choose_move_and_description(board),
            (8, 'The computer blocks a win.'),
        )

    def test_fourth_move_versus_corner_and_two_sides(self):
        board = create_board(
            '01O',
            '3OX',
            'XXO',
        )
        self.assertEqual(
            ai.choose_move_and_description(board),
            (0, 'The computer wins.'),
        )

    def test_fourth_move_versus_two_corners_and_adjacent_side(self):
        board = create_board(
            'X1O',
            '3O5',
            'XXO',
        )
        self.assertEqual(
            ai.choose_move_and_description(board),
            (5, 'The computer wins.'),
        )

    def test_third_move_versus_two_corners(self):
        board = create_board(
            '01O',
            '3O5',
            'X7X',
        )
        self.assertEqual(
            ai.choose_move_and_description(board),
            (7, 'The computer blocks a win.'),
        )

    def test_fourth_move_versus_two_corners(self):
        board = create_board(
            '0XO',
            '3O5',
            'XOX',
        )
        self.assertEqual(
            ai.choose_move_and_description(board),
            (3, 'The computer threatens a win.'),
        )

    def test_fifth_move_versus_two_corners(self):
        board = create_board(
            '0XO',
            'OOX',
            'XOX',
        )
        self.assertEqual(
            ai.choose_move_and_description(board),
            (0, 'The computer gives up.'),
        )

    def test_third_move_versus_corner_and_far_side(self):
        board = create_board(
            '01O',
            '3OX',
            'X78',
        )
        self.assertEqual(
            ai.choose_move_and_description(board),
            (0, 'The computer threatens a win.'),
        )

    def test_fourth_move_versus_corner_and_two_far_sides(self):
        board = create_board(
            'OXO',
            '3OX',
            'X78',
        )
        self.assertEqual(
            ai.choose_move_and_description(board),
            (8, 'The computer wins.'),
        )

    def test_second_move_versus_side(self):
        board = create_board(
            '012',
            '3O5',
            '6X8',
        )
        self.assertEqual(
            ai.choose_move_and_description(board),
            (0, 'The computer plays in the corner.'),
        )

    def test_third_move_versus_side(self):
        board = create_board(
            'O12',
            '3O5',
            '6XX',
        )
        self.assertEqual(
            ai.choose_move_and_description(board),
            (6, 'The computer blocks a win.'),
        )


if __name__ == '__main__':
    main()