from game_state import GameState
from game_token import GameToken
from drop_state import DropState
from game_logic_base import GameLogicBase
from display_console import DisplayConsole
import time


class GameLogicLocal(GameLogicBase):
    ROWS = 6
    COLS = 7

    def __init__(self):
        # Initialize the game board with empty spaces
        self._board = [[' ' for _ in range(self.COLS)] for _ in range(self.ROWS)]
        # Initialize the game state to RED's turn
        self._state = GameState.TURN_RED

    def _check_winner(self, player: GameToken) -> bool:
        for r in range(self.ROWS):
            for c in range(self.COLS - 3):
                if (self._board[r][c] == player and 
                    self._board[r][c+1] == player and 
                    self._board[r][c+2] == player and 
                    self._board[r][c+3] == player):
                    return True

        # vertical check
        for c in range(self.COLS):
            for r in range(self.ROWS - 3):
                if (self._board[r][c] == player and 
                    self._board[r+1][c] == player and 
                    self._board[r+2][c] == player and 
                    self._board[r+3][c] == player):
                    return True

        # positive diagonal check
        for r in range(self.ROWS - 3):
            for c in range(self.COLS - 3):
                if (self._board[r][c] == player and 
                    self._board[r+1][c+1] == player and 
                    self._board[r+2][c+2] == player and 
                    self._board[r+3][c+3] == player):
                    return True

        # negative diagonal check
        for r in range(3, self.ROWS):
            for c in range(self.COLS - 3):
                if (self._board[r][c] == player and 
                    self._board[r-1][c+1] == player and 
                    self._board[r-2][c+2] == player and 
                    self._board[r-3][c+3] == player):
                    return True

        return False
    
    def _check_draw(self) -> bool:
        return all(self._board[self.ROWS-1][c] != ' ' for c in range(self.COLS))

    def get_board(self) -> list:
        return self._board

    def get_state(self) -> GameState:
        return self._state

    def drop_token(self, player: GameToken, column: int) -> DropState:
        if column < 0 or column >= self.COLS:
            return DropState.COLUMN_INVALID
        
        # checks the lowest empty row in column
        row = 5
        for r in range(self.ROWS):
            if self._board[r][column] == ' ':
                row = r
            else:
                r -= 1
                break
        
        if r == -1:
            return DropState.COLUMN_FULL

        # drop animation
        display = DisplayConsole()
        for y in range(row + 1):
            display.draw_grid()  # redraws the grid background
            # redraws dropped tokens
            for r in range(self.ROWS):
                for c in range(self.COLS):
                    token = self._board[r][c]
                    if token != ' ':
                        display.draw_token(c, r, token)
            # board with new token
            display.draw_token(column, y, player)
            time.sleep(0.075)

        # token in last row
        self._board[row][column] = player
            
        if self._check_winner(GameToken.RED):
            self._state = GameState.WON_RED
        elif self._check_winner(GameToken.YELLOW):
            self._state = GameState.WON_YELLOW
        elif self._check_draw():
            self._state = GameState.DRAW
        else:
            # switches turns only if game hasn't ended
            self._state = GameState.TURN_YELLOW if self._state == GameState.TURN_RED else GameState.TURN_RED

        return DropState.DROP_OK