class Board:
    def __init__(self) -> None:
        """
        :params:
            None
        :return:
            None
        
        This is the constructor for the Board class. It sets up the board and the empty spaces. It also sets up the unicode characters for the circles that will be used to represent the pieces.
        """
        self.__green_circle= "\033[32m\u2b24\033[0m"
        self.__red_circle= "\033[31m\u2b24\033[0m"
        self.__board = [[None for _ in range(6)] for _ in range(7)]
        self.__empty_spaces = 42
    
    def __str__(self) -> str:
        return """

        | {5} | {11} | {17} | {23} | {29} | {35} | {41} |
        +---+---+---+---+---+---+---+
        | {4} | {10} | {16} | {22} | {28} | {34} | {40} |
        +---+---+---+---+---+---+---+
        | {3} | {9} | {15} | {21} | {27} | {33} | {39} |
        +---+---+---+---+---+---+---+
        | {2} | {8} | {14} | {20} | {26} | {32} | {38} |
        +---+---+---+---+---+---+---+
        | {1} | {7} | {13} | {19} | {25} | {31} | {37} |
        +---+---+---+---+---+---+---+
        | {0} | {6} | {12} | {18} | {24} | {30} | {36} |
        +---+---+---+---+---+---+---+
        | 1 | 2 | 3 | 4 | 5 | 6 | 7 |

""".format(*[self.__green_circle if i==1 else self.__red_circle if i==2 else " " for row in self.__board for i in row])

    def __repr__(self) -> str:
        return str(self)

    def place(self, column: int, player: int) -> int:
        """
        :params: 
            column: int
            player: int
        :return:
            int
        
        This method places a piece in the board. It will raise an exception if the column is full. It returns the row where the piece was placed.
        """
        for row in range(6):
            if self.__board[column][row] == None:
                self.__board[column][row] = player
                self.__empty_spaces -= 1
                return row
        raise Exception("Column is full already!")

    def is_full(self) -> bool:
        """
        :params:
            None
        :return:
            bool
        
        This method returns True if the board is full, False otherwise.
        """
        return self.__empty_spaces == 0
    
    def reset(self) -> None:
        """
        :params:
            None
        :return:
            None

        This method resets the board.
        """
        self.__board = [[None for _ in range(6)] for _ in range(7)]
        self.__empty_spaces = 42

    def get_board(self) -> list[list[int]]:
        """
        :params:
            None
        :return:
            list[list[int]]

        This method returns the board as a list of lists of ints. 1 represents a green piece, 2 represents a red piece and None represents an empty space.
        """
        return self.__board
    
    def check_cell(self, row: int, column: int) -> int:
        """
        :params:
            row: int
            column: int
        :return:
            int
        
        This method returns the value of the cell in the given row and column. 1 represents a green piece, 2 represents a red piece and None represents an empty space.
        """
        return self.__board[column][row]

