from enum import Enum
from typing import NamedTuple, Optional


class Coords(NamedTuple):
    """
    Вспомогательный класс для упрощения работы с координатами
    """

    x: int | float
    y: int | float

    def __add__(self, other):
        if isinstance(other, self.__class__):
            return self.__class__(self.x + other.x, self.y + other.y)
        if isinstance(other, (int, float)):
            return self.__class__(self.x + other, self.y + other)
        return NotImplemented

    def __sub__(self, other):
        if isinstance(other, self.__class__):
            return self.__class__(self.x - other.x, self.y - other.y)
        if isinstance(other, (int, float)):
            return self.__class__(self.x - other, self.y - other)
        return NotImplemented

    def __floordiv__(self, other):
        if isinstance(other, self.__class__):
            return self.__class__(self.x // other.x, self.y // other.y)
        if isinstance(other, (int, float)):
            return self.__class__(self.x // other, self.y // other)
        return NotImplemented

    def __mul__(self, other):
        if isinstance(other, self.__class__):
            return self.__class__(self.x * other.x, self.y * other.y)
        if isinstance(other, (int, float)):
            return self.__class__(self.x * other, self.y * other)
        return NotImplemented

    def transform(self, ref: "Coords"):
        return self * ref

    def dir_norm(self):
        """нормализация вектора, но только для получения направления
        x, y могут быть только -1, 0, 1
        может быть только направление по горизонтали либо по вертикали
        либо без направления
        """
        src = self
        if self.x and self.y:
            src = (
                self.__class__(self.x, 0)
                if abs(self.x) > abs(self.y)
                else self.__class__(0, self.y)
            )
        return self.__class__(*((n > 0) - (n < 0) for n in src))

    @classmethod
    def zero(cls):
        return cls(0, 0)


class Direction(Enum):
    LEFT = 1
    RIGHT = 2
    UP = 3
    DOWN = 4

    def as_coords(self):
        match self:
            case Direction.LEFT:
                return Coords(-1, 0)
            case Direction.RIGHT:
                return Coords(1, 0)
            case Direction.UP:
                return Coords(0, -1)
            case Direction.DOWN:
                return Coords(0, 1)

    @staticmethod
    def from_coords(coords: Coords) -> Optional["Direction"]:
        match coords.dir_norm():
            case Coords(-1, 0):
                return Direction.LEFT
            case Coords(1, 0):
                return Direction.RIGHT
            case Coords(0, -1):
                return Direction.UP
            case Coords(0, 1):
                return Direction.DOWN