from ASTTypes.ASTNodeSubtypes import Expression
from ASTTypes.ExpressionSubtypes import Operator
from enum import Enum


class BinaryOperator(Operator):
    _Translation = None
    @property
    def Translation(self):
        if self._Translation is not None:
            return self._Translation
        raise Exception(f"Untranslatable operator {self.__class__.__name__}")

    def __init__(self,
                 leftchild: Expression | None = None,
                 rightchild: Expression | None = None):
        super().__init__(children=[None, None])
        if leftchild:
            self.left_child = leftchild
        if rightchild:
            self.right_child = rightchild

    @property
    def left_child(self) -> Expression | None:
        try:
            return self.children[0]
        except IndexError:
            return None

    @left_child.setter
    def left_child(self, value: Expression):
        self.children[0] = value

    @property
    def right_child(self) -> Expression | None:
        try:
            return self.children[1]
        except IndexError:
            return None

    @right_child.setter
    def right_child(self, value: Expression):
        self.children[1] = value

    def translate(self) -> str:
        return f"{self.left_child.translate()}" + f" {self.Translation} " + f"{self.right_child.translate()}"


class UnaryOperatorPlace(Enum):
    Prefix = "prefix"
    Postfix = "postfix"


class UnaryOperator(Operator):
    _Translation = None
    _Position = None

    def translate(self) -> str:
        if not self._Translation or not self._Position:
            raise Exception(f"Untranslatable operator {self.__class__.__name__}")
        if self._Position == UnaryOperatorPlace.Prefix:
            return f"{self._Translation}{self.child.translate()}"
        if self._Position == UnaryOperatorPlace.Postfix:
            return f"{self.child.translate()}{self._Translation}"

    def __init__(self,
                 child: Expression | None = None):
        super().__init__([None])
        if child:
            self.child = child

    @property
    def child(self) -> Expression | None:
        try:
            return self.children[0]
        except IndexError:
            return None

    @child.setter
    def child(self, value: Expression):
        self.children[0] = value
