from abc import ABC, abstractmethod
from classes import Maze, Cell


class Observer(ABC):
    """Интерфейс наблюдателя."""

    @abstractmethod
    def update(self, event: dict) -> None:
        """
        event — словарь с ключом "type":
          "maze_loaded"  — лабиринт загружен
          "path_found"   — путь найден
          "no_path"      — путь не найден
        """
        ...


class ConsoleView(Observer):
    """
    Наблюдатель: выводит лабиринт и путь в консоль.

    Символы:
      #  — стена
      .  — проход
      S  — старт
      E  — выход
      *  — найденный путь
      @  — текущее положение игрока
    """

    def update(self, event: dict) -> None:
        event_type = event.get("type")

        if event_type == "maze_loaded":
            print("\n[ConsoleView] Лабиринт загружен:")
            self.render(event["maze"])

        elif event_type == "path_found":
            print("\n[ConsoleView] Путь найден!")
            self.render(event["maze"], path=event.get("path"), player=event.get("player"))

        elif event_type == "no_path":
            print("\n[ConsoleView] Путь не найден.")

        elif event_type == "move":
            print(f"\n[ConsoleView] Игрок переместился в ({event['x']}, {event['y']})")
            self.render(event["maze"], path=event.get("path"), player=event.get("player"))

    def render(self, maze: Maze, path: list[Cell] | None = None,
               player: Cell | None = None) -> None:
        path_set = set(path) if path else set()

        for y in range(maze.height):
            row_str = ""
            for x in range(maze.width):
                cell = maze.get_cell(x, y)
                if player and cell == player:
                    row_str += "@"
                elif cell.is_start:
                    row_str += "S"
                elif cell.is_exit:
                    row_str += "E"
                elif cell in path_set:
                    row_str += "*"
                elif cell.is_wall:
                    row_str += "#"
                else:
                    row_str += "."
            print(row_str)

