from __future__ import annotations
from empire.python.typings import *
from empire.enums.base_enum import BaseEnum

from empire.betsiamites.python.lexer.tokenizer.token_type import TokenType

__all__ = ['TokenType', 'TokenTypes', 'PythonTokenTypes', 'LITERAL_MAPPING_TO_TOKEN_TYPE']


class TokenTypes(BaseEnum):
    """
    Enum containing all known token types
    """
    # Undefined token types (range below 0)
    UNDEFINED: Final[TokenType] = TokenType(-1, 'UNDEFINED')
    EITHER_VAR_OR_FUNC_CALL: Final[TokenType] = TokenType(-2, 'VAR_OR_FUNC', UNDEFINED)
    EITHER_DICT_OR_SET: Final[TokenType] = TokenType(-3, 'DICT_OR_SET', UNDEFINED)
    UNKNOWN_VAR: Final[TokenType] = TokenType(-4, 'UNKNOWN_VAR', UNDEFINED)

    # Global Token Types (range 0..99)
    UNKNOWN: Final[TokenType] = TokenType(0, 'UNKNOWN')
    KEYWORD: Final[TokenType] = TokenType(1, 'KEYWORD')
    DECORATOR: Final[TokenType] = TokenType(2, 'DECORATOR')  # @a_decoration
    SELF_KW: Final[TokenType] = TokenType(3, 'SELF')
    TYPE_ANNOTATION: Final[TokenType] = TokenType(4, 'TYPE_ANNOTATION')  # a_var: int
    RETURN_TYPE_ANNOTATION: Final[TokenType] = TokenType(5, 'RETURN_TYPE_ANNOTATION')  # -> ...
    EXCEPTION_RAISE: Final[TokenType] = TokenType(6, 'EXCEPT_RAISE')  # raise ThisTokenIsAnExceptRaise()
    EXCEPTION_CATCH: Final[TokenType] = TokenType(7, 'EXCEPT_CATCH')  # except ThisTokenIsAnExceptCatch

    # Class variables token types (range 100..109)
    CLASS_VARIABLE: Final[TokenType] = TokenType(100, 'CLASS_VAR')  # every variable that is of TokenType type in this class is a Class Var
    CLASS_VARIABLE_DECL: Final[TokenType] = TokenType(101, 'DECL', CLASS_VARIABLE, is_declare=True)
    CLASS_VARIABLE_ACCESSOR: Final[TokenType] = TokenType(101, 'ACCESS', CLASS_VARIABLE, is_accessor=True)
    CLASS_VARIABLE_MODIFIER: Final[TokenType] = TokenType(102, 'MODIF', CLASS_VARIABLE, is_modifier=True)

    # Function parameter token types (range 110..119)
    FUNCTION_PARAMETER: Final[TokenType] = TokenType(110, 'FUNC_PARAM')
    FUNCTION_PARAMETER_DECL: Final[TokenType] = TokenType(111, 'DECL', FUNCTION_PARAMETER, is_declare=True)  # parameters in function declaration
    FUNCTION_PARAMETER_ACCESSOR: Final[TokenType] = TokenType(112, 'ACCESS', FUNCTION_PARAMETER, is_accessor=True)  # within function param access
    FUNCTION_PARAMETER_MODIFIER: Final[TokenType] = TokenType(113, 'MODIF', FUNCTION_PARAMETER, is_modifier=True)  # within function param modif
    FUNCTION_PARAMETER_DEFINITION: Final[TokenType] = TokenType(114, 'DEF', FUNCTION_PARAMETER)  # when performing a func call and defining param values
    FUNCTION_PARAMETER_DEFAULT_VALUE: Final[TokenType] = TokenType(115, 'DEF_VALUE', FUNCTION_PARAMETER)

    # Variables token types (range 120..129)
    VARIABLE: Final[TokenType] = TokenType(120, 'VAR')
    VARIABLE_DECL: Final[TokenType] = TokenType(121, 'DECL', VARIABLE, is_declare=True)  # a_var
    VARIABLE_ACCESSOR: Final[TokenType] = TokenType(122, 'ACCESS', VARIABLE, is_accessor=True)  # a_var.get() || if a_var || print(a_var) || etc..
    VARIABLE_MODIFIER: Final[TokenType] = TokenType(123, 'MODIF', VARIABLE, is_modifier=True)  # a_var = 123

    # Function token types (range 130..139)
    FUNCTION: Final[TokenType] = TokenType(130, 'FUNC')
    FUNCTION_DECL: Final[TokenType] = TokenType(131, 'DECL', FUNCTION, is_declare=True)  # def patate()
    FUNCTION_CALL: Final[TokenType] = TokenType(132, 'CALL', FUNCTION)  # patate()
    FUNCTION_POINTER: Final[TokenType] = TokenType(133, 'PTR', FUNCTION)  # something = patate

    # Class token types (range 140..149)
    CLASS: Final[TokenType] = TokenType(140, 'CLASS')  # consider AClass...
    CLASS_DECL: Final[TokenType] = TokenType(141, 'DECL', CLASS, is_declare=True)  # class AClass:
    CLASS_ACCESS: Final[TokenType] = TokenType(142, 'ACCESS', CLASS, is_accessor=True)  # AClass.method()
    CLASS_CTOR_CALL: Final[TokenType] = TokenType(143, 'CTOR_CALL', CLASS, is_accessor=True)  # AClass()
    PARENT_CLASS: Final[TokenType] = TokenType(144, 'PARENT', CLASS)  # def BClass(AClass):

    # Imports token types (range 150..159)
    IMPORT: Final[TokenType] = TokenType(150, 'IMPORT')
    MODULE_IMPORT: Final[TokenType] = TokenType(151, 'MODULE', IMPORT)
    PACKAGE_IMPORT: Final[TokenType] = TokenType(152, 'PACKAGE', IMPORT)
    IMPORT_ALL_STAR: Final[TokenType] = TokenType(153, '*', IMPORT)
    BUILTIN_PACKAGE: TokenType = (154, 'BUILTIN_PACKAGE', IMPORT)

    # Instance variables token type (range 160..169)
    INSTANCE_VARIABLE: Final[TokenType] = TokenType(160, 'INST_VAR')
    INSTANCE_VARIABLE_ACCESS: Final[TokenType] = TokenType(161, 'ACCESS', INSTANCE_VARIABLE, is_accessor=True)
    INSTANCE_VARIABLE_MODIFIER: Final[TokenType] = TokenType(161, 'MODIF', INSTANCE_VARIABLE, is_modifier=True)

    # Literals token types (range 200..219)
    LITERAL: Final[TokenType] = TokenType(200, 'LITERAL')
    LITERAL_INT_NUMBER: Final[TokenType] = TokenType(201, 'INT', LITERAL)
    LITERAL_FLOAT_NUMBER: Final[TokenType] = TokenType(202, 'FLOAT', LITERAL)
    LITERAL_IMAGINARY_NUMBER: Final[TokenType] = TokenType(203, 'IMAGINARY', LITERAL)
    LITERAL_NONE: Final[TokenType] = TokenType(204, 'NONE', LITERAL)
    LITERAL_TRUE: Final[TokenType] = TokenType(205, 'TRUE', LITERAL)
    LITERAL_FALSE: Final[TokenType] = TokenType(206, 'FALSE', LITERAL)
    LITERAL_STRING: Final[TokenType] = TokenType(207, 'STRING', LITERAL)
    LITERAL_SQ_STRING: Final[TokenType] = TokenType(208, 'SQ_STRING', LITERAL_STRING)
    LITERAL_DQ_STRING: Final[TokenType] = TokenType(209, 'DQ_STRING', LITERAL_STRING)
    LITERAL_TQ_STRING: Final[TokenType] = TokenType(210, 'TQ_STRING', LITERAL_STRING)
    LITERAL_DOCUMENTATION: Final[TokenType] = TokenType(211, 'DOCUMENTATION', LITERAL)

    # Typings token types (range 220..299)
    TYPINGS: Final[TokenType] = TokenType(220, 'TYPE')
    TYPINGS_NONE: Final[TokenType] = TokenType(221, 'NONE', TYPINGS)
    TYPINGS_STR: Final[TokenType] = TokenType(222, 'STR', TYPINGS)
    TYPINGS_INT: Final[TokenType] = TokenType(223, 'INT', TYPINGS)
    TYPINGS_FLOAT: Final[TokenType] = TokenType(224, 'FLOAT', TYPINGS)
    TYPINGS_BOOL: Final[TokenType] = TokenType(225, 'BOOL', TYPINGS)
    TYPINGS_BYTES: Final[TokenType] = TokenType(226, 'BYTES', TYPINGS)
    TYPINGS_BYTEARRAY: Final[TokenType] = TokenType(227, 'BYTE_ARRAY', TYPINGS)
    TYPINGS_COMPLEX: Final[TokenType] = TokenType(228, 'COMPLEX', TYPINGS)
    TYPINGS_DICT: Final[TokenType] = TokenType(229, 'DICT', TYPINGS)
    TYPINGS_FROZEN_SET: Final[TokenType] = TokenType(230, 'FROZEN_SET', TYPINGS)
    TYPINGS_LIST: Final[TokenType] = TokenType(231, 'LIST', TYPINGS)
    TYPINGS_MAP: Final[TokenType] = TokenType(232, 'MAP', TYPINGS)
    TYPINGS_SET: Final[TokenType] = TokenType(233, 'SET', TYPINGS)
    TYPINGS_TUPLE: Final[TokenType] = TokenType(234, 'TUPLE', TYPINGS)
    TYPINGS_TYPE: Final[TokenType] = TokenType(235, 'TYPE', TYPINGS)
    TYPINGS_OBJECT: Final[TokenType] = TokenType(236, 'OBJECT', TYPINGS)
    TYPINGS_GENERATOR: Final[TokenType] = TokenType(237, 'GENERATOR', TYPINGS)
    TYPINGS_UNION: Final[TokenType] = TokenType(238, 'UNION', TYPINGS)
    TYPINGS_OPTIONAL: Final[TokenType] = TokenType(239, 'OPTIONAL', TYPINGS)
    TYPINGS_COUNTER: Final[TokenType] = TokenType(240, 'COUNTER', TYPINGS)
    TYPINGS_DEQUE: Final[TokenType] = TokenType(241, 'DEQUE', TYPINGS)
    TYPINGS_CHAIN_MAP: Final[TokenType] = TokenType(242, 'CHAIN_MAP', TYPINGS)
    TYPINGS_GENERIC: Final[TokenType] = TokenType(243, 'GENERIC', TYPINGS)
    TYPINGS_PROTOCOL: Final[TokenType] = TokenType(244, 'PROTOCOL', TYPINGS)
    TYPINGS_CALLABLE: Final[TokenType] = TokenType(245, 'CALLABLE', TYPINGS)
    TYPINGS_CLASS_VAR: Final[TokenType] = TokenType(246, 'CLASS_VAR', TYPINGS)
    TYPINGS_ANY: Final[TokenType] = TokenType(247, 'ANY', TYPINGS)
    TYPINGS_USER_DEFINED: Final[TokenType] = TokenType(248, 'USER_DEFINED', TYPINGS)  # name can be changed

    # OPERATORS (300 - 499)
    OPERATOR: Final[TokenType] = TokenType(300, 'OP')

    # Arithmetic Operators token types (range 301..319)
    OPERATOR_ARITHMETIC: Final[TokenType] = TokenType(301, 'ARITHM', OPERATOR)
    OPERATOR_ADD: Final[TokenType] = TokenType(302, 'ADD', OPERATOR_ARITHMETIC, is_operator=True)  # +
    OPERATOR_MINUS: Final[TokenType] = TokenType(303, 'MINUS', OPERATOR_ARITHMETIC, is_operator=True)  # -
    OPERATOR_MULTIPLY: Final[TokenType] = TokenType(304, 'MULT', OPERATOR_ARITHMETIC, is_operator=True)  # *
    OPERATOR_DIVIDE: Final[TokenType] = TokenType(305, 'DIVIDE', OPERATOR_ARITHMETIC, is_operator=True)  # /
    OPERATOR_FLOOR_DIVIDE: Final[TokenType] = TokenType(306, 'FDIVIDE', OPERATOR_ARITHMETIC, is_operator=True)  # //
    OPERATOR_MODULO: Final[TokenType] = TokenType(307, 'MODULO', OPERATOR_ARITHMETIC, is_operator=True)  # %
    OPERATOR_EXPONENT: Final[TokenType] = TokenType(308, 'EXPONENT', OPERATOR_ARITHMETIC, is_operator=True)  # **
    OPERATOR_MATRIX_MULTIPLY: Final[TokenType] = TokenType(309, 'MATMUL', OPERATOR_ARITHMETIC, is_operator=True)  # @
    OPERATOR_POSITIVE: Final[TokenType] = TokenType(310, 'POSITIVE', OPERATOR_ARITHMETIC, is_operator=True)  # +
    OPERATOR_NEGATIVE: Final[TokenType] = TokenType(311, 'NEGATIVE', OPERATOR_ARITHMETIC, is_operator=True)  # -

    # Assignment operators token types (range 320..359)
    OPERATOR_ASSIGN: Final[TokenType] = TokenType(320, 'ASSIGN', OPERATOR, is_operator=True)  # =
    OPERATOR_ASSIGN_ADD: Final[TokenType] = TokenType(321, 'ADD', OPERATOR_ASSIGN, is_operator=True)  # +=
    OPERATOR_ASSIGN_MINUS: Final[TokenType] = TokenType(322, 'MINUS', OPERATOR_ASSIGN, is_operator=True)  # -=
    OPERATOR_ASSIGN_MULTIPLY: Final[TokenType] = TokenType(323, 'MULT', OPERATOR_ASSIGN, is_operator=True)  # *=
    OPERATOR_ASSIGN_DIVIDE: Final[TokenType] = TokenType(324, 'DIVIDE', OPERATOR_ASSIGN, is_operator=True)  # /=
    OPERATOR_ASSIGN_FLOOR_DIVIDE: Final[TokenType] = TokenType(325, 'FDIVIDE', OPERATOR_ASSIGN, is_operator=True)  # //=
    OPERATOR_ASSIGN_MODULO: Final[TokenType] = TokenType(326, 'MODULO', OPERATOR_ASSIGN, is_operator=True)  # %=
    OPERATOR_ASSIGN_EXPONENT: Final[TokenType] = TokenType(327, 'EXPONENT', OPERATOR_ASSIGN, is_operator=True)  # **=
    OPERATOR_ASSIGN_BIT_AND: Final[TokenType] = TokenType(328, 'BIT_AND', OPERATOR_ASSIGN, is_operator=True)  # &=
    OPERATOR_ASSIGN_BIT_OR: Final[TokenType] = TokenType(329, 'BIT_OR', OPERATOR_ASSIGN, is_operator=True)  # |=
    OPERATOR_ASSIGN_BIT_NOT: Final[TokenType] = TokenType(330, 'BIT_NOT', OPERATOR_ASSIGN, is_operator=True)  # ~=
    OPERATOR_ASSIGN_BIT_XOR: Final[TokenType] = TokenType(331, 'BIT_XOR', OPERATOR_ASSIGN, is_operator=True)  # ^=
    OPERATOR_ASSIGN_LSHIFT: Final[TokenType] = TokenType(332, 'BIT_LSHIFT', OPERATOR_ASSIGN, is_operator=True)  # <<=
    OPERATOR_ASSIGN_RSHIFT: Final[TokenType] = TokenType(333, 'BIT_RSHIFT', OPERATOR_ASSIGN, is_operator=True)  # >>=
    OPERATOR_ASSIGN_MATRIX_MULTIPLY: Final[TokenType] = TokenType(334, 'MATMUL', OPERATOR_ASSIGN, is_operator=True) # @=

    # Comparison operators token types (360..379)
    OPERATOR_COMPARISON: Final[TokenType] = TokenType(360, 'COMP', OPERATOR, is_operator=True)
    OPERATOR_COMP_EQUALS: Final[TokenType] = TokenType(361, 'EQUALS', OPERATOR_COMPARISON, is_operator=True)  # ==
    OPERATOR_COMP_NOT_EQUALS: Final[TokenType] = TokenType(362, 'NOT_EQUALS', OPERATOR_COMPARISON, is_operator=True)  # != OR <>
    OPERATOR_COMP_LESSER: Final[TokenType] = TokenType(363, 'LESSER', OPERATOR_COMPARISON, is_operator=True)  # <
    OPERATOR_COMP_LESSER_EQUALS: Final[TokenType] = TokenType(364, 'LESSER_EQUALS', OPERATOR_COMPARISON, is_operator=True)  # <=
    OPERATOR_COMP_GREATER: Final[TokenType] = TokenType(365, 'GREATER', OPERATOR_COMPARISON, is_operator=True)  # >
    OPERATOR_COMP_GREATER_EQUALS: Final[TokenType] = TokenType(366, 'GREATER_EQUALS', OPERATOR_COMPARISON, is_operator=True)  # >=
    OPERATOR_IS: Final[TokenType] = TokenType(367, 'IS', OPERATOR_COMPARISON, is_operator=True)
    OPERATOR_IN: Final[TokenType] = TokenType(368, 'IN', OPERATOR_COMPARISON, is_operator=True)

    # Logical operators token types (380..389)
    OPERATOR_LOGICAL: Final[TokenType] = TokenType(380, 'LOGICAL', OPERATOR, is_operator=True)
    OPERATOR_LOGICAL_AND: Final[TokenType] = TokenType(381, 'AND', OPERATOR_LOGICAL, is_operator=True)
    OPERATOR_LOGICAL_NOT: Final[TokenType] = TokenType(382, 'NOT', OPERATOR_LOGICAL, is_operator=True)
    OPERATOR_LOGICAL_OR: Final[TokenType] = TokenType(383, 'OR', OPERATOR_LOGICAL, is_operator=True)

    # Bitwise operator token types (390..409)
    OPERATOR_BITWISE: Final[TokenType] = TokenType(390, 'BITWISE', OPERATOR, is_operator=True)
    OPERATOR_BIT_AND: Final[TokenType] = TokenType(391, 'BIT_AND', OPERATOR_BITWISE, is_operator=True)  # &
    OPERATOR_BIT_OR: Final[TokenType] = TokenType(392, 'BIT_OR', OPERATOR_BITWISE, is_operator=True)  # |
    OPERATOR_BIT_NOT: Final[TokenType] = TokenType(393, 'BIT_NOT', OPERATOR_BITWISE, is_operator=True)  # ~
    OPERATOR_BIT_XOR: Final[TokenType] = TokenType(394, 'BIT_XOR', OPERATOR_BITWISE, is_operator=True)  # ^
    OPERATOR_BIT_LSHIFT: Final[TokenType] = TokenType(395, 'BIT_LSHIFT', OPERATOR_BITWISE, is_operator=True)  # <<
    OPERATOR_BIT_RSHIFT: Final[TokenType] = TokenType(396, 'BIT_RSHIFT', OPERATOR_BITWISE, is_operator=True)  # >>

    # Misc operators token types (410..499)
    OPERATOR_MEMBER_ACCESS: Final[TokenType] = TokenType(411, 'MEMBER_ACCESS', OPERATOR, is_operator=True)  # .
    OPERATOR_SUBSCRIPT_OPEN: Final[TokenType] = TokenType(412, 'SUBSCRIPT_OPEN', OPERATOR, is_operator=True)  # [
    OPERATOR_SUBSCRIPT_CLOSE: Final[TokenType] = TokenType(413, 'SUBSCRIPT_CLOSE', OPERATOR, is_operator=True)  # ]
    OPERATOR_PAREN_OPEN: Final[TokenType] = TokenType(414, 'PAREN_OPEN', OPERATOR, is_operator=True)  # (
    OPERATOR_PAREN_CLOSE: Final[TokenType] = TokenType(415, 'PAREN_CLOSE', OPERATOR, is_operator=True)  # )
    OPERATOR_CURLY_OPEN: Final[TokenType] = TokenType(416, 'CURLY_OPEN', OPERATOR, is_operator=True)  # {
    OPERATOR_CURLY_CLOSE: Final[TokenType] = TokenType(417, 'CURLY_CLOSE', OPERATOR, is_operator=True)  # }
    OPERATOR_COMMA: Final[TokenType] = TokenType(418, 'COMMA', OPERATOR, is_operator=True)  # ,
    OPERATOR_COLON: Final[TokenType] = TokenType(419, 'COLON', OPERATOR, is_operator=True)  # :
    OPERATOR_DECORATOR: Final[TokenType] = TokenType(420, 'DECORATOR', OPERATOR, is_operator=True)  # @
    OPERATOR_LAMBDA: Final[TokenType] = TokenType(421, 'LAMBDA', OPERATOR, is_operator=True)  # lambda
    OPERATOR_RETURN_TYPE: Final[TokenType] = TokenType(422, 'RETURN_TYPE', OPERATOR, is_operator=True)  # ->
    OPERATOR_CONCAT: Final[TokenType] = TokenType(423, 'CONCAT', OPERATOR, is_operator=True)  # +
    OPERATOR_ASSIGN_CONCAT: Final[TokenType] = TokenType(424, 'ASSIGN_CONCAT', OPERATOR, is_operator=True)  # +=
    OPERATOR_DEL: Final[TokenType] = TokenType(425, 'DEL', OPERATOR, is_operator=True)  # del
    OPERATOR_ARGS: Final[TokenType] = TokenType(426, 'ARGS', OPERATOR, is_operator=True)  # *
    OPERATOR_KWARGS: Final[TokenType] = TokenType(427, 'KWARGS', OPERATOR, is_operator=True)  # **

    # SPECIALS (500 - 999)
    # Data structure definitions token types (500..510)
    SPECIALS_DICTIONARY_DEFINITION_START: Final[TokenType] = TokenType(500, 'START_DICT_DEF')
    SPECIALS_DICTIONARY_DEFINITION_END: Final[TokenType] = TokenType(501, 'END_DICT_DEF')
    SPECIALS_TUPLE_DEFINITION_START: Final[TokenType] = TokenType(502, 'START_TUPLE_DEF')
    SPECIALS_TUPLE_DEFINITION_END: Final[TokenType] = TokenType(503, 'END_TUPLE_DEF')
    SPECIALS_LIST_DEFINITION_START: Final[TokenType] = TokenType(504, 'START_LIST_DEF')
    SPECIALS_LIST_DEFINITION_END: Final[TokenType] = TokenType(505, 'END_LIST_DEF')
    SPECIALS_DICTIONARY_FUNCTION: Final[TokenType] = TokenType(506, 'DICT()')
    SPECIALS_TUPLE_FUNCTION: Final[TokenType] = TokenType(507, 'TUPLE()')
    SPECIALS_LIST_FUNCTION: Final[TokenType] = TokenType(508, 'LIST()')
    SPECIALS_SET_FUNCTION: Final[TokenType] = TokenType(509, 'SET()')
    SPECIALS_TBD_FUNCTION: Final[TokenType] = TokenType(510, 'SPEC_TBD_FN')

    # Other data structure token types (520..529)
    DATA_STRUCTURE_SUBSCRIPT: Final[TokenType] = TokenType(520, 'DS_SUBSCRIPT')
    DICTIONARY_KEY: Final[TokenType] = TokenType(521, 'DICT_KEY', DATA_STRUCTURE_SUBSCRIPT)
    DATA_STRUCTURE_INDEX: Final[TokenType] = TokenType(522, 'IDX', DATA_STRUCTURE_SUBSCRIPT)

    # FUNCTIONS TOKENS (1000...9999)
    # Magic Functions (1000...1999)
    MAGIC_FUNCTION: Final[TokenType] = TokenType(1000, 'MAGIC')
    MAGIC_INIT: Final[TokenType] = TokenType(1001, 'INIT', MAGIC_FUNCTION)
    MAGIC_NEW: Final[TokenType] = TokenType(1002, 'NEW', MAGIC_FUNCTION)
    MAGIC_ADD: Final[TokenType] = TokenType(1003, 'ADD', MAGIC_FUNCTION)
    MAGIC_SUB: Final[TokenType] = TokenType(1004, 'SUB', MAGIC_FUNCTION)
    MAGIC_MUL: Final[TokenType] = TokenType(1005, 'MUL', MAGIC_FUNCTION)
    MAGIC_FLOOR_DIV: Final[TokenType] = TokenType(1006, 'FLOOR_DIV', MAGIC_FUNCTION)
    MAGIC_DIV: Final[TokenType] = TokenType(1007, 'DIV', MAGIC_FUNCTION)
    MAGIC_MOD: Final[TokenType] = TokenType(1008, 'MOD', MAGIC_FUNCTION)
    MAGIC_POW: Final[TokenType] = TokenType(1009, 'POW', MAGIC_FUNCTION)
    MAGIC_LSHIFT: Final[TokenType] = TokenType(1010, 'LSHIFT', MAGIC_FUNCTION)
    MAGIC_RSHIFT: Final[TokenType] = TokenType(1011, 'RSHIFT', MAGIC_FUNCTION)
    MAGIC_AND: Final[TokenType] = TokenType(1012, 'AND', MAGIC_FUNCTION)
    MAGIC_XOR: Final[TokenType] = TokenType(1013, 'XOR', MAGIC_FUNCTION)
    MAGIC_OR: Final[TokenType] = TokenType(1014, 'OR', MAGIC_FUNCTION)
    MAGIC_IADD: Final[TokenType] = TokenType(1015, 'IADD', MAGIC_FUNCTION)
    MAGIC_ISUB: Final[TokenType] = TokenType(1016, 'ISUB', MAGIC_FUNCTION)
    MAGIC_IMUL: Final[TokenType] = TokenType(1017, 'IMUL', MAGIC_FUNCTION)
    MAGIC_IDIV: Final[TokenType] = TokenType(1018, 'IDIV', MAGIC_FUNCTION)
    MAGIC_IFLOOR_DIV: Final[TokenType] = TokenType(1019, 'IFLOOR_DIV', MAGIC_FUNCTION)
    MAGIC_IMOD: Final[TokenType] = TokenType(1020, 'IMOD', MAGIC_FUNCTION)
    MAGIC_IPOW: Final[TokenType] = TokenType(1021, 'IPOW', MAGIC_FUNCTION)
    MAGIC_ILSHIFT: Final[TokenType] = TokenType(1022, 'ILSHIFT', MAGIC_FUNCTION)
    MAGIC_IRSHIFT: Final[TokenType] = TokenType(1023, 'IRSHIFT', MAGIC_FUNCTION)
    MAGIC_IAND: Final[TokenType] = TokenType(1024, 'IAND', MAGIC_FUNCTION)
    MAGIC_IXOR: Final[TokenType] = TokenType(1025, 'IXOR', MAGIC_FUNCTION)
    MAGIC_IOR: Final[TokenType] = TokenType(1026, 'IOR', MAGIC_FUNCTION)
    MAGIC_NEG: Final[TokenType] = TokenType(1027, 'NEG', MAGIC_FUNCTION)
    MAGIC_POS: Final[TokenType] = TokenType(1028, 'POS', MAGIC_FUNCTION)
    MAGIC_ABS: Final[TokenType] = TokenType(1029, 'ABS', MAGIC_FUNCTION)
    MAGIC_INVERT: Final[TokenType] = TokenType(1030, 'INVERT', MAGIC_FUNCTION)
    MAGIC_INV: Final[TokenType] = TokenType(1031, 'INV', MAGIC_FUNCTION)
    MAGIC_COMPLEX: Final[TokenType] = TokenType(1032, 'COMPLEX', MAGIC_FUNCTION)
    MAGIC_INT: Final[TokenType] = TokenType(1033, 'INT', MAGIC_FUNCTION)
    MAGIC_LONG: Final[TokenType] = TokenType(1034, 'LONG', MAGIC_FUNCTION)
    MAGIC_FLOAT: Final[TokenType] = TokenType(1035, 'FLOAT', MAGIC_FUNCTION)
    MAGIC_OCT: Final[TokenType] = TokenType(1036, 'OCT', MAGIC_FUNCTION)
    MAGIC_HEX: Final[TokenType] = TokenType(1037, 'HEX', MAGIC_FUNCTION)
    MAGIC_LT: Final[TokenType] = TokenType(1038, 'LT', MAGIC_FUNCTION)
    MAGIC_LE: Final[TokenType] = TokenType(1039, 'LE', MAGIC_FUNCTION)
    MAGIC_EQ: Final[TokenType] = TokenType(1040, 'EQ', MAGIC_FUNCTION)
    MAGIC_NE: Final[TokenType] = TokenType(1041, 'NE', MAGIC_FUNCTION)
    MAGIC_GE: Final[TokenType] = TokenType(1042, 'GE', MAGIC_FUNCTION)
    MAGIC_GT: Final[TokenType] = TokenType(1043, 'GT', MAGIC_FUNCTION)
    MAGIC_DEL: Final[TokenType] = TokenType(1044, 'DEL', MAGIC_FUNCTION)
    MAGIC_CMP: Final[TokenType] = TokenType(1045, 'CMP', MAGIC_FUNCTION)
    MAGIC_ROUND: Final[TokenType] = TokenType(1046, 'ROUND', MAGIC_FUNCTION)
    MAGIC_FLOOR: Final[TokenType] = TokenType(1047, 'FLOOR', MAGIC_FUNCTION)
    MAGIC_CEIL: Final[TokenType] = TokenType(1048, 'CEIL', MAGIC_FUNCTION)
    MAGIC_TRUNC: Final[TokenType] = TokenType(1049, 'TRUNC', MAGIC_FUNCTION)
    MAGIC_TRUE_DIV: Final[TokenType] = TokenType(1050, 'TRUE_DIV', MAGIC_FUNCTION)
    MAGIC_DIV_MOD: Final[TokenType] = TokenType(1051, 'DIV_MOD', MAGIC_FUNCTION)
    MAGIC_RADD: Final[TokenType] = TokenType(1052, 'RADD', MAGIC_FUNCTION)
    MAGIC_RSUB: Final[TokenType] = TokenType(1053, 'RSUB', MAGIC_FUNCTION)
    MAGIC_RMUL: Final[TokenType] = TokenType(1054, 'RMUL', MAGIC_FUNCTION)
    MAGIC_RFLOOR_DIV: Final[TokenType] = TokenType(1055, 'RFLOOR_DIV', MAGIC_FUNCTION)
    MAGIC_RDIV: Final[TokenType] = TokenType(1056, 'RDIV', MAGIC_FUNCTION)
    MAGIC_RTRUE_DIV: Final[TokenType] = TokenType(1057, 'RTRUE_DIV', MAGIC_FUNCTION)
    MAGIC_RMOD: Final[TokenType] = TokenType(1058, 'RMOD', MAGIC_FUNCTION)
    MAGIC_RDIV_MOD: Final[TokenType] = TokenType(1059, 'RDIV_MOD', MAGIC_FUNCTION)
    MAGIC_RPOW: Final[TokenType] = TokenType(1060, 'RPOW', MAGIC_FUNCTION)
    MAGIC_RLSHIFT: Final[TokenType] = TokenType(1061, 'RLSHIFT', MAGIC_FUNCTION)
    MAGIC_RRSHIFT: Final[TokenType] = TokenType(1062, 'RRSHIFT', MAGIC_FUNCTION)
    MAGIC_RAND: Final[TokenType] = TokenType(1063, 'RAND', MAGIC_FUNCTION)
    MAGIC_ROR: Final[TokenType] = TokenType(1064, 'ROR', MAGIC_FUNCTION)
    MAGIC_RXOR: Final[TokenType] = TokenType(1065, 'RXOR', MAGIC_FUNCTION)
    MAGIC_ITRUE_DIV: Final[TokenType] = TokenType(1066, 'ITRUE_DIV', MAGIC_FUNCTION)
    MAGIC_INDEX: Final[TokenType] = TokenType(1067, 'INDEX', MAGIC_FUNCTION)
    MAGIC_COERCE: Final[TokenType] = TokenType(1068, 'COERCE', MAGIC_FUNCTION)
    MAGIC_STR: Final[TokenType] = TokenType(1069, 'STR', MAGIC_FUNCTION)
    MAGIC_REPR: Final[TokenType] = TokenType(1070, 'REPR', MAGIC_FUNCTION)
    MAGIC_UNICODE: Final[TokenType] = TokenType(1071, 'UNICODE', MAGIC_FUNCTION)
    MAGIC_FORMAT: Final[TokenType] = TokenType(1072, 'FORMAT', MAGIC_FUNCTION)
    MAGIC_HASH: Final[TokenType] = TokenType(1073, 'HASH', MAGIC_FUNCTION)
    MAGIC_NON_ZERO: Final[TokenType] = TokenType(1074, 'NON_ZERO', MAGIC_FUNCTION)
    MAGIC_DIR: Final[TokenType] = TokenType(1075, 'DIR', MAGIC_FUNCTION)
    MAGIC_SIZEOF: Final[TokenType] = TokenType(1076, 'SIZEOF', MAGIC_FUNCTION)
    MAGIC_GET_ATTR: Final[TokenType] = TokenType(1077, 'GET_ATTR', MAGIC_FUNCTION)
    MAGIC_SET_ATTR: Final[TokenType] = TokenType(1078, 'SET_ATTR', MAGIC_FUNCTION)
    MAGIC_DEL_ATTR: Final[TokenType] = TokenType(1079, 'DEL_ATTR', MAGIC_FUNCTION)
    MAGIC_GET_ATTRIBUTE: Final[TokenType] = TokenType(1080, 'GET_ATTRIBUTE', MAGIC_FUNCTION)
    MAGIC_LEN: Final[TokenType] = TokenType(1081, 'LEN', MAGIC_FUNCTION)
    MAGIC_GET_ITEM: Final[TokenType] = TokenType(1082, 'GET_ITEM', MAGIC_FUNCTION)
    MAGIC_SET_ITEM: Final[TokenType] = TokenType(1083, 'SET_ITEM', MAGIC_FUNCTION)
    MAGIC_DEL_ITEM: Final[TokenType] = TokenType(1084, 'DEL_ITEM', MAGIC_FUNCTION)
    MAGIC_ITER: Final[TokenType] = TokenType(1085, 'ITER', MAGIC_FUNCTION)
    MAGIC_REVERSED: Final[TokenType] = TokenType(1086, 'REVERSED', MAGIC_FUNCTION)
    MAGIC_CONTAINS: Final[TokenType] = TokenType(1087, 'CONTAINS', MAGIC_FUNCTION)
    MAGIC_MISSING: Final[TokenType] = TokenType(1088, 'MISSING', MAGIC_FUNCTION)
    MAGIC_INSTANCE_CHECK: Final[TokenType] = TokenType(1089, 'INSTANCE_CHECK', MAGIC_FUNCTION)
    MAGIC_SUB_CLASS_CHECK: Final[TokenType] = TokenType(1090, 'SUB_CLASS_CHECK', MAGIC_FUNCTION)
    MAGIC_CALL: Final[TokenType] = TokenType(1091, 'CALL', MAGIC_FUNCTION)
    MAGIC_ENTER: Final[TokenType] = TokenType(1092, 'ENTER', MAGIC_FUNCTION)
    MAGIC_EXIT: Final[TokenType] = TokenType(1093, 'EXIT', MAGIC_FUNCTION)
    MAGIC_GET: Final[TokenType] = TokenType(1094, 'GET', MAGIC_FUNCTION)
    MAGIC_SET: Final[TokenType] = TokenType(1095, 'SET', MAGIC_FUNCTION)
    MAGIC_DELETE: Final[TokenType] = TokenType(1096, 'DELETE', MAGIC_FUNCTION)
    MAGIC_COPY: Final[TokenType] = TokenType(1097, 'COPY', MAGIC_FUNCTION)
    MAGIC_DEEP_COPY: Final[TokenType] = TokenType(1098, 'DEEP_COPY', MAGIC_FUNCTION)
    MAGIC_GET_INIT_ARGS: Final[TokenType] = TokenType(1099, 'GET_INIT_ARGS', MAGIC_FUNCTION)
    MAGIC_GET_NEW_ARGS: Final[TokenType] = TokenType(1100, 'GET_NEW_ARGS', MAGIC_FUNCTION)
    MAGIC_GET_STATE: Final[TokenType] = TokenType(1101, 'GET_STATE', MAGIC_FUNCTION)
    MAGIC_SET_STATE: Final[TokenType] = TokenType(1102, 'SET_STATE', MAGIC_FUNCTION)
    MAGIC_REDUCE: Final[TokenType] = TokenType(1103, 'REDUCE', MAGIC_FUNCTION)
    MAGIC_REDUCE_EX: Final[TokenType] = TokenType(1104, 'REDUCE_EX', MAGIC_FUNCTION)
    MAGIC_BOOL: Final[TokenType] = TokenType(1105, 'BOOL', MAGIC_FUNCTION)
    MAGIC_BYTES: Final[TokenType] = TokenType(1106, 'BYTES', MAGIC_FUNCTION)
    MAGIC_MAT_MUL: Final[TokenType] = TokenType(1107, 'MATMUL', MAGIC_FUNCTION)
    MAGIC_IMAT_MUL: Final[TokenType] = TokenType(1108, 'IMATMUL', MAGIC_FUNCTION)
    MAGIC_RMAT_MUL: Final[TokenType] = TokenType(1109, 'RMATMUL', MAGIC_FUNCTION)

    # Other Python Dunder Functions token types (2000..2999)
    # https://docs.python.org/3/library/stdtypes.html#other-built-in-types
    DUNDER_FUNCTION: Final[TokenType] = TokenType(2000, 'DUNDER')
    DUNDER_DICT: Final[TokenType] = TokenType(2001, 'DICT', DUNDER_FUNCTION)  # object.__dict__
    DUNDER_CLASS: Final[TokenType] = TokenType(2002, 'CLASS', DUNDER_FUNCTION)  # instance.__class__
    DUNDER_BASES: Final[TokenType] = TokenType(2003, 'BASES', DUNDER_FUNCTION)  # class.__bases__
    DUNDER_NAME: Final[TokenType] = TokenType(2004, 'NAME', DUNDER_FUNCTION)  # definition.__name__
    DUNDER_QUALNAME: Final[TokenType] = TokenType(2005, 'QUALNAME', DUNDER_FUNCTION)  # definition.__qualname__
    DUNDER_MRO: Final[TokenType] = TokenType(2006, 'MRO', DUNDER_FUNCTION)  # class.__mro__
    DUNDER_SUBCLASSES: Final[TokenType] = TokenType(2007, 'SUBCLASSES', DUNDER_FUNCTION)  # class.__subclasses__
    DUNDER_SELF: Final[TokenType] = TokenType(2008, 'SELF', DUNDER_FUNCTION)  # __self__
    DUNDER_FUNC: Final[TokenType] = TokenType(2009, 'FUNC', DUNDER_FUNCTION)  # __func__

    # Builtin functions token types (9000..9999)  (only map risky functions such as compile(), exec()... others should be of type BUILTIN_FUNCTION)
    BUILTIN_FUNCTION: Final[TokenType] = TokenType(9000, 'BUILTIN_FUNCTION')  # ex: mro(), int(), etc..
    BUILTIN_FUNCTION_COMPILE: Final[TokenType] = TokenType(9001, 'COMPILE', BUILTIN_FUNCTION)
    BUILTIN_FUNCTION_EXEC: Final[TokenType] = TokenType(9002, 'EXEC', BUILTIN_FUNCTION)
    BUILTIN_FUNCTION_EVAL: Final[TokenType] = TokenType(9003, 'EVAL', BUILTIN_FUNCTION)
    BUILTIN_FUNCTION_PRINT: Final[TokenType] = TokenType(9004, 'PRINT', BUILTIN_FUNCTION)
    BUILTIN_FUNCTION_INPUT: Final[TokenType] = TokenType(9005, 'INPUT', BUILTIN_FUNCTION)


LITERAL_MAPPING_TO_TOKEN_TYPE: Dict[type, TokenType] = {
    bool: TokenTypes.TYPINGS_BOOL,
    str: TokenTypes.TYPINGS_STR,
    int: TokenTypes.TYPINGS_INT,
    float: TokenTypes.TYPINGS_FLOAT,
    complex: TokenTypes.TYPINGS_COMPLEX,
    bytes: TokenTypes.TYPINGS_BYTES,
    bytearray: TokenTypes.TYPINGS_BYTEARRAY,
    dict: TokenTypes.TYPINGS_DICT,
    frozenset: TokenTypes.TYPINGS_FROZEN_SET,
    list: TokenTypes.TYPINGS_LIST,
    map: TokenTypes.TYPINGS_MAP,
    set: TokenTypes.TYPINGS_SET,
    tuple: TokenTypes.TYPINGS_TUPLE,
    type: TokenTypes.TYPINGS_TYPE,
    object: TokenTypes.TYPINGS_OBJECT
}


class PythonTokenTypes(BaseEnum):
    ENDMARKER: Final[int] = 0
    NAME: Final[int] = 1
    NUMBER: Final[int] = 2
    STRING: Final[int] = 3
    NEWLINE: Final[int] = 4
    INDENT: Final[int] = 5
    DEDENT: Final[int] = 6
    LPAR: Final[int] = 7
    RPAR: Final[int] = 8
    LSQB: Final[int] = 9
    RSQB: Final[int] = 10
    COLON: Final[int] = 11
    COMMA: Final[int] = 12
    SEMI: Final[int] = 13
    PLUS: Final[int] = 14
    MINUS: Final[int] = 15
    STAR: Final[int] = 16
    SLASH: Final[int] = 17
    VBAR: Final[int] = 18
    AMPER: Final[int] = 19
    LESS: Final[int] = 20
    GREATER: Final[int] = 21
    EQUAL: Final[int] = 22
    DOT: Final[int] = 23
    PERCENT: Final[int] = 24
    LBRACE: Final[int] = 25
    RBRACE: Final[int] = 26
    EQEQUAL: Final[int] = 27
    NOTEQUAL: Final[int] = 28
    LESSEQUAL: Final[int] = 29
    GREATEREQUAL: Final[int] = 30
    TILDE: Final[int] = 31
    CIRCUMFLEX: Final[int] = 32
    LEFTSHIFT: Final[int] = 33
    RIGHTSHIFT: Final[int] = 34
    DOUBLESTAR: Final[int] = 35
    PLUSEQUAL: Final[int] = 36
    MINEQUAL: Final[int] = 37
    STAREQUAL: Final[int] = 38
    SLASHEQUAL: Final[int] = 39
    PERCENTEQUAL: Final[int] = 40
    AMPEREQUAL: Final[int] = 41
    VBAREQUAL: Final[int] = 42
    CIRCUMFLEXEQUAL: Final[int] = 43
    LEFTSHIFTEQUAL: Final[int] = 44
    RIGHTSHIFTEQUAL: Final[int] = 45
    DOUBLESTAREQUAL: Final[int] = 46
    DOUBLESLASH: Final[int] = 47
    DOUBLESLASHEQUAL: Final[int] = 48
    AT: Final[int] = 49
    ATEQUAL: Final[int] = 50
    RARROW: Final[int] = 51
    ELLIPSIS: Final[int] = 52
    COLONEQUAL: Final[int] = 53
    OP: Final[int] = 54
    AWAIT: Final[int] = 55
    ASYNC: Final[int] = 56
    TYPE_IGNORE: Final[int] = 57
    TYPE_COMMENT: Final[int] = 58
    # These aren't used by the C tokenizer but are needed for tokenize.py
    ERRORTOKEN: Final[int] = 59
    COMMENT: Final[int] = 60
    NL: Final[int] = 61
    ENCODING: Final[int] = 62
    N_TOKENS : Final[int]= 63
    # Special definitions for cooperation with parser
    NT_OFFSET: Final[int] = 256

    _MAPPING: Dict[int, str] = {
        0: 'ENDMARKER',
        1: 'NAME',
        2: 'NUMBER',
        3: 'STRING',
        4: 'NEWLINE',
        5: 'INDENT',
        6: 'DEDENT',
        7: 'LPAR',
        8: 'RPAR',
        9: 'LSQB',
        10: 'RSQB',
        11: 'COLON',
        12: 'COMMA',
        13: 'SEMI',
        14: 'PLUS',
        15: 'MINUS',
        16: 'STAR',
        17: 'SLASH',
        18: 'VBAR',
        19: 'AMPER',
        20: 'LESS',
        21: 'GREATER',
        22: 'EQUAL',
        23: 'DOT',
        24: 'PERCENT',
        25: 'LBRACE',
        26: 'RBRACE',
        27: 'EQEQUAL',
        28: 'NOTEQUAL',
        29: 'LESSEQUAL',
        30: 'GREATEREQUAL',
        31: 'TILDE',
        32: 'CIRCUMFLEX',
        33: 'LEFTSHIFT',
        34: 'RIGHTSHIFT',
        35: 'DOUBLESTAR',
        36: 'PLUSEQUAL',
        37: 'MINEQUAL',
        38: 'STAREQUAL',
        39: 'SLASHEQUAL',
        40: 'PERCENTEQUAL',
        41: 'AMPEREQUAL',
        42: 'VBAREQUAL',
        43: 'CIRCUMFLEXEQUAL',
        44: 'LEFTSHIFTEQUAL',
        45: 'RIGHTSHIFTEQUAL',
        46: 'DOUBLESTAREQUAL',
        47: 'DOUBLESLASH',
        48: 'DOUBLESLASHEQUAL',
        49: 'AT',
        50: 'ATEQUAL',
        51: 'RARROW',
        52: 'ELLIPSIS',
        53: 'COLONEQUAL',
        54: 'OP',
        55: 'AWAIT',
        56: 'ASYNC',
        57: 'TYPE_IGNORE',
        58: 'TYPE_COMMENT',
        59: 'ERRORTOKEN',
        60: 'COMMENT',
        61: 'NL',
        62: 'ENCODING',
        63: 'N_TOKENS',
        256: 'NT_OFFSET'
    }

    @staticmethod
    def to_string(value: int) -> str:
        return PythonTokenTypes._MAPPING.get(value, 'unknown({})'.format(value))


# class TokenTypesOld:
#     # Updated for Python 3.8.2
#
#
#     @staticmethod
#     def parse_typing(typing_string: str, is_return_type: bool = False) -> Tuple[int, str]:
#         typing_string = typing_string.lower()
#         if typing_string == 'none':
#             return TokenTypes.TYPINGS_NONE if is_return_type else TokenTypes.TYPINGS_OPTIONAL
#         elif typing_string == 'str': return TokenTypes.TYPINGS_STR
#         elif typing_string == 'int': return TokenTypes.TYPINGS_INT
#         elif typing_string == 'float': return TokenTypes.TYPINGS_FLOAT
#         elif typing_string == 'bool': return TokenTypes.TYPINGS_BOOL
#         elif typing_string == 'bytes': return TokenTypes.TYPINGS_BYTES
#         elif typing_string == 'bytearray': return TokenTypes.TYPINGS_BYTEARRAY
#         elif typing_string == 'complex': return TokenTypes.TYPINGS_COMPLEX
#         elif typing_string == 'dict' or typing_string == 'mapping': return TokenTypes.TYPINGS_DICT
#         elif typing_string == 'frozenset': return TokenTypes.TYPINGS_FROZEN_SET
#         elif typing_string == 'list': return TokenTypes.TYPINGS_LIST
#         elif typing_string == 'map': return TokenTypes.TYPINGS_MAP
#         elif typing_string == 'set': return TokenTypes.TYPINGS_SET
#         elif typing_string == 'tuple': return TokenTypes.TYPINGS_TUPLE
#         elif typing_string == 'type': return TokenTypes.TYPINGS_TYPE
#         elif typing_string == 'object': return TokenTypes.TYPINGS_OBJECT
#         elif typing_string == 'union': return TokenTypes.TYPINGS_UNION
#         elif typing_string == 'optional': return TokenTypes.TYPINGS_OPTIONAL
#         elif typing_string == 'counter': return TokenTypes.TYPINGS_COUNTER
#         elif typing_string == 'deque': return TokenTypes.TYPINGS_DEQUE
#         elif typing_string == 'chainmap': return TokenTypes.TYPINGS_CHAIN_MAP
#         elif typing_string == 'generic': return TokenTypes.TYPINGS_GENERIC
#         elif typing_string == 'callable': return TokenTypes.TYPINGS_CALLABLE
#         elif typing_string == 'classvar': return TokenTypes.TYPINGS_CLASS_VAR
#         elif typing_string == 'any': return TokenTypes.TYPINGS_ANY
#         else:
#             Log.debug('Unsupported type', __file__, get_function_name(), the_type=typing_string)
#             return TokenTypes.UNKNOWN
