from task2.strategyObjects.pathFindingStrategy import PathFindingStrategy
from task2.strategyObjects.util import restorePath

from task2.mazeObjects.maze import Maze
from task2.mazeObjects.cell import Cell
from task2.mazeObjects.path import Path

import queue

class BFS(PathFindingStrategy):
    """Поиск в ширину – гарантирует кратчайший путь по количеству шагов.
    Возвращает None, если пути нет"""
    def findPath(self, maze: Maze, start: Cell, exit: Cell) -> Path:
        visited = dict()
        parents = dict()
        q = queue.Queue()

        q.put(start)
        visited[start] = 0
        parents[start] = None

        found_exit = False
        while not q.empty():
            current = q.get()

            # Условие нахождение выхода
            if current.isExit:
                found_exit = True
                break

            # Перебор соседей
            for hood in maze.getNeighbors(current):
                if hood in visited:
                    continue
                visited[hood] = visited[current] + 1
                parents[hood] = current
                q.put(hood)
        
        if not found_exit:
            path_list = None
        else:
            path_list = restorePath(parents, exit)
        return Path(path_list, len(visited))