from ASTTypes.ASTNode import ASTNode
from typing import Self, List
from enum import Enum, unique, EnumMeta


class TokenTypeEnumMeta (EnumMeta):
    def __getitem__(self, item):
        try:
            return super().__getitem__(item)
        except (KeyError, TypeError) as err:
            raise SyntaxError(f"Unknown token type {item}.") from err


@unique
class TokenType(str, Enum, metaclass=TokenTypeEnumMeta):
    """Token type enum type.
    Symbol: Linguistic symbol (aka variable)
    Operator: Operator (aka +, -...)
    Structure: Structuring components of the language. (aka braces, semicolons!"""
    Symbol = 'Symbol'
    Operator = 'Operator'
    Structure = 'Structure'
    Number = 'Number'
    Word = 'Word'
    Quote = 'Quote'


class Token(ASTNode):
    """Token class
    Tokens can be of type TokenType
    They are terminals - They can not have children"""
    def __init__(self, value: str, token_type, line: int | None = None, col: int | None = None):
        self.line = line
        self.col = col
        self.token_type: TokenType = token_type
        super().__init__('token', value)

    def __eq__(self, other):
        if isinstance(other, type(self)) and self.value == other.value and self.token_type == other.token_type:
            return True
        return False

    def __repr__(self):
        return self.value

    def __hash__(self):
        return hash(self.__repr__())


class Expression(ASTNode):
    """Node type for ALL expressions and expression subtypes"""
    def __init__(self, children: List[Self] = None):
        children = children or []
        super().__init__('expression', None, children)


class Statement(Expression):
    """Expression alias; Expression solely on a row, that is ended by a semicolon
    Gets evaluated for side effects."""
    def __init__(self, children: List[Expression] = None):
        self.comment: str | None = None
        children = children or []
        super().__init__(children)

    @classmethod
    def from_Expression(cls, expression: Expression) -> Self:
        return cls(expression.children)

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


class CompoundStatement(Statement):
    pass


class StatementList(ASTNode):
    """Simple list of statements, delimited by semicolon (usualy enclosed in curly braces as a block)"""
    def __init__(self, children: List[Statement] = None):
        children = children or []
        super().__init__('statement list', None, children)
