import time


class SearchStats:
    def __init__(self, time_ms, visited_cells, path_length):
        self.time_ms = time_ms
        self.visited_cells = visited_cells
        self.path_length = path_length


class MazeSolver:
    def __init__(self, maze, strategy):
        self.maze = maze
        self.strategy = strategy
        self.observers = []

    def set_strategy(self, strategy):
        self.strategy = strategy

    def add_observer(self, observer):
        self.observers.append(observer)

    def notify(self, event):
        for observer in self.observers:
            observer.update(event)

    def solve(self):
        self.notify("search_started")

        start_time = time.perf_counter()

        path, visited_cells = self.strategy.find_path(
            self.maze,
            self.maze.start,
            self.maze.exit
        )

        end_time = time.perf_counter()

        self.notify("search_finished")

        time_ms = (end_time - start_time) * 1000

        stats = SearchStats(
            time_ms=time_ms,
            visited_cells=visited_cells,
            path_length=len(path)
        )

        return stats, path