import time
from Maze import Maze
from strategy import PathFindingStrategy


class SearchStats:
    def __init__(self, execution_time, visited_count, path_length, path):
        self.execution_time = execution_time
        self.visited_count = visited_count
        self.path_length = path_length
        self.path = path

    def __str__(self):
        return ("f == Статистика поиска == =\n"
                f"Время выполнения: {self.execution_time_ms:.4f} мс\n"
                f"Посещено клеток:  {self.visited_count}\n"
                f"Длина пути:       {self.path_length} клеток\n")


class MazeSolver:
    def __init__(self, maze: Maze, strategy: PathFindingStrategy):
        self._maze = maze
        self._strategy = strategy
        self._observers = []

    def addObserver(self, observer):
        """Регистрация нового наблюдателя (например, ConsoleView)"""
        self._observers.append(observer)

    def notify(self, event):
        """Уведомление всех подписчиков о событии"""
        for observer in self._observers:
            observer.update(event)

    def setStrategy(self, strategy):
        self._strategy = strategy

    def solve(self):

        if not self._maze or not self._strategy:
            raise ValueError("Не задан лабиринт или стратегия поиска!")

        start_time = time.perf_counter()

        path, visited_count = self._strategy.findPath(
            self._maze, self._maze.start, self._maze.exit)

        end_time = time.perf_counter()

        execution_time_ms = (end_time - start_time) * 1000

        path_length = len(path)

        from ConsoleView import Event
        self.notify(Event("path_found", {"maze": self._maze, "path": path}))

        return SearchStats(execution_time_ms, visited_count, path_length, path)
