import heapq
from strategies.pathfinding_strategy import PathFindingStrategy


class AStarStrategy(PathFindingStrategy):
    name = "A*"

    def heuristic(self, cell, exitCell):
        return abs(cell.x - exitCell.x) + abs(cell.y - exitCell.y)

    def findPath(self, maze, start, exitCell):
        self.visitedCount = 0
        if start is None or exitCell is None:
            return []

        open_set = []
        heapq.heappush(open_set, (0, 0, start.x, start.y, start))
        parent = {}
        g_score = {(start.x, start.y): 0}
        closed = set()

        while open_set:
            f_score, current_g, _, _, current = heapq.heappop(open_set)
            pos = (current.x, current.y)

            if pos in closed:
                continue

            closed.add(pos)
            self.visitedCount += 1

            if current.x == exitCell.x and current.y == exitCell.y:
                return self._restore_path(parent, start, exitCell)

            for neighbor in maze.getNeighbors(current):
                npos = (neighbor.x, neighbor.y)
                tentative_g = current_g + getattr(neighbor, "weight", 1)

                if tentative_g < g_score.get(npos, float("inf")):
                    g_score[npos] = tentative_g
                    parent[npos] = current
                    new_f = tentative_g + self.heuristic(neighbor, exitCell)
                    heapq.heappush(open_set, (new_f, tentative_g, neighbor.x, neighbor.y, neighbor))

        return []
