from ASTTypes.ExpressionSubtypes import Operator
from ASTTypes.OperatorSubtypes import BinaryOperator, UnaryOperator, UnaryOperatorPlace
from ASTTypes.ASTNodeSubtypes import Token
from ASTTypes.ASTNode import ASTNode
from ASTTypes.ExpressionSubtypes import Symbol, SymbolType, ParensStructure
from ASTTypes.ASTNodeSubtypes import Expression
from typing import Dict, Type, List, Tuple
from enum import Enum, auto
from ASTTypes.ASTNode import ContextType

class OperatorMultiplication(BinaryOperator):
    PRIORITY = 190  # LA
    _Translation = "*"


class OperatorDivision(BinaryOperator):
    PRIORITY = 190  # LA
    _Translation = "/"


class OperatorModulo(BinaryOperator):
    PRIORITY = 190  # LA
    _Translation = "%"


class OperatorRepetition(BinaryOperator):
    PRIORITY = 190  # LA



class OperatorList(BinaryOperator):
    PRIORITY = 50  # LA

    def __init__(self,
                 leftchild: Expression | None = None,
                 rightchild: Expression | None = None):
        super().__init__()
        self.children = []
        if isinstance(leftchild, type(self)):
            self.children.extend(leftchild.children)
        else:
            self.children.append(leftchild)
        if isinstance(rightchild, type(self)):
            self.children.extend(rightchild.children)
        else:
            self.children.append(rightchild)


class OperatorLessThan(BinaryOperator):
    PRIORITY = 140  # LA (AsChained)
    _Translation = "<"


class OperatorGreaterThan(BinaryOperator):
    PRIORITY = 140  # LA (AsChained)
    _Translation = ">"


class OperatorLessOrEqual(BinaryOperator):
    PRIORITY = 140  # LA (AsChained)
    _Translation = "<="


class OperatorGreaterOrEqual(BinaryOperator):
    PRIORITY = 140  # LA (AsChained)
    _Translation = ">="


class OperatorLessThan_str(BinaryOperator):
    PRIORITY = 140  # LA (AsChained)
    _Translation = "<"


class OperatorGreaterThan_str(BinaryOperator):
    PRIORITY = 140  # LA (AsChained)
    _Translation = ">"


class OperatorLessOrEqual_str(BinaryOperator):
    PRIORITY = 140  # LA (AsChained)
    _Translation = "<="


class OperatorGreaterOrEqual_str(BinaryOperator):
    PRIORITY = 140  # LA (AsChained)
    _Translation = ">="

class OperatorPlus_bin(BinaryOperator):
    PRIORITY = 180
    _Translation = "+"


class OperatorPlus_un(UnaryOperator):
    _Translation = "+"
    _Position = UnaryOperatorPlace.Prefix
    PRIORITY = 210


class OperatorMinus_bin(BinaryOperator):
    PRIORITY = 180
    _Translation = "-"


class OperatorMinus_un(UnaryOperator):
    PRIORITY = 210
    _Translation = "-"
    _Position = UnaryOperatorPlace.Prefix


class OperatorConcatenation(BinaryOperator):
    PRIORITY = 180  # LA
    _Translation = "+"


class OperatorNot(UnaryOperator):
    PRIORITY = 210  # RA
    _Translation = "!"
    _Position = UnaryOperatorPlace.Prefix


class OperatorMY(Operator):
    PRIORITY = 260

    def __init__(self, children):
        super().__init__(children)
        self.want_context = self.children[0].want_context

    def translate(self) -> str:
        return "var " + ", ".join([child.translate() for child in self.children])


class OperatorAssignment(BinaryOperator):
    PRIORITY = 60
    _Translation = "="

    @property
    def context(self) -> ContextType:
        return self._context

    @context.setter
    def context(self, value):
        self._context = value
        try:
            for child in self.children:
                child.context = self.left_child.want_context
        except AttributeError:
            raise SyntaxError("Assigninment to something weird, can't figure out context")


class OperatorEquals(BinaryOperator):
    PRIORITY = 130  # LA as chained
    _Translation = "=="


class OperatorNotEquals(BinaryOperator):
    PRIORITY = 130  # LA as chained
    _Translation = "!="


class OperatorEquals_str(BinaryOperator):
    PRIORITY = 130  # LA as chained
    _Translation = "=="


class OperatorNotEquals_str(BinaryOperator):
    PRIORITY = 130
    _Translation = "!="


class OperatorPRINT(Operator):
    PRIORITY = 40

    def translate(self) -> str:
        args = [child.translate() for child in self.children]
        return f"print({', '.join(args)})"


class OperatorFUNCTION(Operator):
    PRIORITY = 40

    def __init__(self, name: str, children: list[Expression]):
        self.name = name
        super().__init__(children)

    def __repr__(self):
        return f"{self.name} {super().__repr__()}"

    def translate(self) -> str:
        args = [child.translate() for child in self.children]
        return f"{self.name}({', '.join(args)})"


class OperatorPredecrement(UnaryOperator):
    PRIORITY = 230
    _Translation = "--"
    _Position = UnaryOperatorPlace.Prefix


class OperatorPostdecrement(UnaryOperator):
    PRIORITY = 230
    _Translation = "--"
    _Position = UnaryOperatorPlace.Postfix


class OperatorPreincrement(UnaryOperator):
    PRIORITY = 230
    _Translation = "++"
    _Position = UnaryOperatorPlace.Prefix


class OperatorPostincrement(UnaryOperator):
    PRIORITY = 230
    _Position = UnaryOperatorPlace.Postfix
    _Translation = "++"


class OperatorSHIFT(Operator):
    PRIORITY = 260

    @ASTNode.context.setter
    def context(self, value):
        self._context = value
        for child in self.children:
            child.context = ContextType.LIST

    def translate(self) -> str:
        return f"{self.children[0].translate()}.shift()"
