from abc import ABC, abstractmethod
from typing import List

from maze import Maze, Cell


class Command(ABC):
    """Интерфейс команды (Command pattern)."""
    
    @abstractmethod
    def execute(self) -> bool:
        pass
    
    @abstractmethod
    def undo(self):
        pass


class Player:
    """Игрок, перемещающийся по лабиринту."""
    
    def __init__(self, cell: Cell):
        self.current_cell = cell
        self._history: List[Cell] = []
    
    def move_to(self, cell: Cell):
        self._history.append(self.current_cell)
        self.current_cell = cell
    
    def move_back(self):
        if self._history:
            self.current_cell = self._history.pop()
            return self.current_cell
        return None
    
    def __repr__(self):
        return f"Player({self.current_cell.x}, {self.current_cell.y})"


class MoveCommand(Command):
    """Команда перемещения игрока."""
    
    DIRECTIONS = {
        'W': (0, -1),
        'S': (0, 1),
        'A': (-1, 0),
        'D': (1, 0),
    }
    
    def __init__(self, player: Player, maze: Maze, direction: str):
        self.player = player
        self.maze = maze
        self.direction = direction.upper()
        self._previous_cell = None
        self._executed = False
    
    def execute(self) -> bool:
        if self.direction not in self.DIRECTIONS:
            return False
        
        dx, dy = self.DIRECTIONS[self.direction]
        new_x = self.player.current_cell.x + dx
        new_y = self.player.current_cell.y + dy
        
        new_cell = self.maze.get_cell(new_x, new_y)
        
        if new_cell and new_cell.is_passable():
            self._previous_cell = self.player.current_cell
            self.player.move_to(new_cell)
            self._executed = True
            return True
        
        return False
    
    def undo(self):
        if self._executed and self._previous_cell:
            self.player.current_cell = self._previous_cell
            self._executed = False
            self._previous_cell = None