class Player:
    NUM_OF_ROWS = 10
    NUM_OF_COLS = 10
    SHIP_NOT_FOUND = -1
    WIN = True
    GAME_ON = False
    HIT = 1

    # A constructor for a player in the Battleship game receiving a the player's name, and
    # a file containing the player's ships as parameter
    def __init__(self, player_name, player_ships):
        self._name = player_name
        self._ships = (Player.parse_ships(player_ships))[:]
        self._board = Board(Player.NUM_OF_ROWS, Player.NUM_OF_COLS, self._ships)
        self._opponent_board = Board(Player.NUM_OF_ROWS, Player.NUM_OF_COLS, None)
        self._opponent_ship_sank = list()

    # Parse the player's ships-file and returns a list containing each ship's indexes
    @staticmethod
    def parse_ships(player_ships):
        ships_file = open(player_ships)
        file_lines = ships_file.readlines()
        ships = [] * len(file_lines)
        for i in xrange(len(file_lines)):
		    ships.append([])
		    splitted_line = (file_lines[i].split(","))[:]
		    for cell in splitted_line:       # Separating the lines into indexes			
				ship_index = [ord(cell[0].lower()) - 97, int(cell[1:]) - 1]    # Parsing each cell
				ships[i].append(ship_index)
        return ships

    # Parses the given massage string into a cell in the game board ([row, col])
    @staticmethod
    def parse_move(move):
        move = move.split(" ")
        attack_index = [ord(move[0].lower()) - 97, int(move[1]) - 1]
        return attack_index

    # Returns a list with the indexes of the ship who covers the cell given as parameter [row,col]
    def find_ship(self, index):
        for i in xrange(len(self._ships)):
            for cell in self._ships[i]:
                if (cell[0] == index[0]) and (cell[1] == index[1]):
                    return self._ships[i]
        return Player.SHIP_NOT_FOUND

    # Adds to the _opponent_ship_sank list the indexes of the ship who covers the
    # given index, recursively.
    def find_opponent_ship(self, index):
        for i in xrange(-1, 2):
            for j in xrange(-1, 2):
                neighbor = (index[0] + i, index[1] + j)
                if 0 <= neighbor[0] <= 9 and 0 <= neighbor[1] <= 9:
                    if (neighbor not in self._opponent_ship_sank) and \
                                    self._opponent_board.get_cell_value(neighbor) == "H":
                        self._opponent_ship_sank.append(neighbor)

    # Checks the impact of the given move on this player's board, and updtes the board accordingly
    def check_move(self, move):
        index = Player.parse_move(move)[:]
        if self._board.check_cell(index) == Player.HIT:
            self._board.mark_as_hit(index)		# Marks the cell as HIT
            ship = self.find_ship(index)[:]
            if self._board.is_ship_sunk(ship):  # Checks if an entire ship was hit (hence sank)
                self._board.mark_ship_as_sunk(ship)		# Marks the ship as sunk
                if self.did_player_loose():    # Checks whether all the player's ship sank
                    return "ALL_SHIP_SANK"
                return "SHIP_SANK"
            return "HIT"
        self._board.mark_as_miss(index)		# Marks the cell as MISSED
        return "MISS"

    # Checks whether all the player's ships sank and returns True if so, False otherwise
    def did_player_loose(self):
        for ship in self._ships:
            if not self._board.is_ship_sunk(ship):
                return False
        return True

    # Updates the opponent's board according to the given opponent reponse
    def update_opponent_board(self, msg, row, col):
        if "MISS" in msg:
            self._opponent_board.mark_as_miss([row, col])
        elif "HIT" in msg:
            self._opponent_board.mark_as_hit([row, col])
        elif "SHIP" in msg:
            self._opponent_board.mark_as_hit([row, col])
            self.find_opponent_ship([row, col])
            self._opponent_board.mark_ship_as_sunk(self._opponent_ship_sank)
            if "ALL" in msg:
                return Player.WIN
        return Player.GAME_ON

    # Prints the player's board
    def print_board(self):
        print self._board