import is_goal
import Sucessors


def queens_opt(path):
    """
    Heuristic for the N-Queens problem that calculates the minimum number of moves
    required to move each queen to a position where it is not in conflict with any other queen.
    
    Args:
    path (list): The path taken so far, where the last element is the current state of the N-Queens board.

    Returns:
    int: The heuristic value, which is the sum of the minimum moves for all queens.
    """
    state = path[-1]  # Extracting the current state from the path
    n = len(state)  # Size of the board (N x N)
    total_moves = 0

    for y in range(n):
        for x in range(n):
            if state[y][x] == 1:  # If there's a queen at (y, x)
                min_moves = n  # Max possible moves
                # Check for a safe spot in each column
                for col in range(n):
                    if col != x:
                        conflict = False
                        # Check row and diagonals for conflict
                        for k in range(n):
                            if state[y][k] == 1 and k != x:
                                conflict = True
                                break
                            if y + (col - x) < n and y + (col - x) >= 0 and state[y + (col - x)][col] == 1:
                                conflict = True
                                break
                            if y - (col - x) < n and y - (col - x) >= 0 and state[y - (col - x)][col] == 1:
                                conflict = True
                                break
                        if not conflict:
                            min_moves = min(min_moves, abs(col - x))
                total_moves += min_moves

    return total_moves




def maze_opt(path):
    """maze search heuristic going to have to use the euclidian distance, so it works for any maze"""
    state = path[-1]
    return (is_goal.MAZE_GOAL[0] - state[0])**2 + (is_goal.MAZE_GOAL[1] - state[1])**2


def puzzle_opt(path):
    current_state = path[-1]
    total = 0
    for i in range(len(current_state)):
        for j in range(len(current_state[i])):
            total = total + abs(is_goal.PUZZLE_GOAL[i][j] - current_state[i][j])
    return total


def sudoku_opt(path):
    starting_point = [Sucessors.choose_best_subsquare(path[-1]), Sucessors.choose_best_rows(path[-1]),
                      Sucessors.choose_best_column(path[-1])]
    return max(starting_point, key=lambda w: w[2])[-1]


def queens_opt(path):
    pass