from heapq import *


from source.strategy import PathFindingStrategy, reconstruct_path
from source.classes import Maze, Cell


class Dijkstra(PathFindingStrategy):
    @property
    def name(self) -> str:
        """Возвращает название метода"""
        return "Dijkstra"


    def findPath(self, maze: Maze):
        start_cell = maze.start
        exit_cell = maze.exit

        queue = []
        counter = 0 # счётчик для уникальности, чтобы не сравнивать клетки

        heappush(queue, (0, counter, start_cell))
        counter += 1

        cost_visited = {start_cell.getXY(): 0}
        came_from = {start_cell.getXY(): None}
        visited_count = 1

        while queue:
            current_cost, _, current_cell = heappop(queue)

            if current_cell.getXY() == exit_cell.getXY():
                return reconstruct_path(
                    came_from=came_from, 
                    start=start_cell, 
                    end=current_cell
                        ), visited_count

            next_cells = maze.getNeighbors(current_cell)

            for next_cell in next_cells:
                neighbor_cost = next_cell.value
                neighbor_cell_xy = next_cell.getXY()

                new_cost = current_cost + neighbor_cost

                if neighbor_cell_xy not in cost_visited or new_cost < cost_visited[neighbor_cell_xy]:
                    heappush(queue, (new_cost, counter, next_cell))
                    counter += 1
                    
                    cost_visited[neighbor_cell_xy] = new_cost
                    came_from[neighbor_cell_xy] = current_cell
                    visited_count += 1
        
        return [], visited_count

