import random
from Constants import *
from Move import *

#
# AIPlayerUtils.py
#
# a set of methods that are likely to be handy for all kinds of AI
# players.
#
# ImportchessPiece Note:  All the methods in this file that take a GameState object
# will not attempt to access the 'board' member of the at object.  This makes
# these routines safe for a GameState that has been generated via the
# GameState.fastclone method.
#

##
# legalCoord
#
# determines whether a given coordinate is legal or not
#
#Parameters:
#   coord        - an x,y coordinate
#
# Return: true (legal) or false (illegal)
def legalCoord(coord):

    #make sure we have a tuple or list with two elements in it
    try:
        if (len(coord) != 2):
            return False
    except TypeError:
        print ("ERROR:  parameter to legalCoord was not a tuple or list")
        raise

    x = coord[0]
    y = coord[1]
    return ( (x >= 0) and (x < BOARD_LENGTH) and (y >= 0) and (y < BOARD_LENGTH))

##
# getChessPieceList()
#
# builds a list of all chessPieces that meet a given specification
#
# Parameters:
#     currentState - a GameState or Node
#     pid   - all chessPieces must belong to this player id.  Pass None to
#             indicate any player
#     types - a tuple of all the chessPiece types wchessPieceed (see ConstchessPieces.py)
#
def getChessPieceList(currentState,
               pid = None,
               types = (BISHOP, KING, KNIGHT, PAWN, QUEEN, ROOK) ):

    #start with a list of all chessPieces that belong to the indicated player(s)
    allChessPieces = []
    for inv in currentState.inventories:
        if (pid == None) or (pid == inv.player):
            allChessPieces += inv.chessPieces

    #fill the result with chessPieces that are of the right type
    result = []
    for chessPiece in allChessPieces:
        if chessPiece.type in types:
            result.append(chessPiece)

    return result
        
##
# getChessPieceAt
#
# determines which chessPiece is at a given coordinate
#
# Parameters:
#    state  - a valid GameState object
#    coords - a valid coordinate (code does not check for invalid!)
#
# Return:  the chessPiece at the coordinate or None if there is none
def getChessPieceAt(state, coords):
    #get a list of all constructs
    allChessPieces = getChessPieceList(state)

    #search for one at the given coord
    for chessPiece in allChessPieces:
        if (chessPiece.coords == coords):
            return chessPiece

    return None  #not found
    
    
##
# listAllMovementMoves
#
# calculates all valid MOVE_ANT moves for the current player in a
# given GameState
#
# Parameters:
#   currentState - the current state
#
# Returns:  a list of Move objects
def listAllMovementMoves(currentState, player):
    result = []

    # first get all moves for each chessPiece belonging to the player
    for chessPiece in player.pieces:

        #create a Move object for each valid movement
        moves, attacks = chessPiece.getValidMoves()
        
        allMoves = moves + attacks

        # construct the list of Moves using the destination coordinates
        for destinationCoordinates in allMoves:            
            result.append(player.createMove([chessPiece.coords, destinationCoordinates]))

    return result

##
# listAllLegalMoves
#
# determines all the legal moves that can be made by the player
# whose turn it currently is.
#
# Parameters:
#   currentState - the current state
#
# Returns:  a list of Move objects
def listAllLegalMoves(currentState, player):
    return listAllMovementMoves(currentState, player)

##
# Return: a reference to the inventory of the player whose turn it is
def getCurrPlayerInventory(currentState):
    #Get my inventory
    resultInv = None
    for inv in currentState.inventories:
        if inv.player == currentState.whoseTurn:
            resultInv = inv
            break
        
    return resultInv
      
##
# returns a character representation of a given chessPiece
# (helper for asciiPrintState)
def charRepChessPiece(chessPiece):
    if (chessPiece == None):
        return " "
    elif (chessPiece.type == BISHOP):
        return "B"
    elif (chessPiece.type == KING):
        return "K"
    elif (chessPiece.type == KNIGHT):
        return "N"
    elif (chessPiece.type == PAWN):
        return "P"
    elif (chessPiece.type == QUEEN):
        return "Q"
    elif (chessPiece.type == ROOK):
        return "R"
    else:
        return "?"

##
# returns a character representation of a given location
# (helper for asciiPrintState)
def charRepLoc(loc):
    if (loc == None):
        return " "
    elif (loc.chessPiece != None):
        return charRepChessPiece(loc.chessPiece)
    else:
        return "."

##
# asciiPrintState
#
# prints a text representation of a GameState to stdout.  This is useful for
# debugging.
#
# Parameters:
#    state - the state to print
#
def asciiPrintState(state):
    #select coordinate ranges such that board orientation will match the GUI
    #for either player
    coordRange = range(0,BOARD_LENGTH)
    colIndexes = " 01234567"
    if (state.whoseTurn == PLAYER_BLACK):
        coordRange = range(BOARD_LENGTH-1,-1,-1)
        colIndexes = " 76543210"

    #print the board with a border of column/row indexes
    print (colIndexes)
    index = 0              #row index
    for x in coordRange:
        row = str(x)
        for y in coordRange:
            chessPiece = getChessPieceAt(state, (y, x))
            if (chessPiece != None):
                row += charRepChessPiece(chessPiece)
            else:
                row += "."
        print (row + str(x))
        index += 1
    print (colIndexes)

