from typing import Callable, NoReturn, Literal, Protocol, Optional

from mdk.types.context import StateScope
from mdk.types.expressions import ConvertibleExpression, Expression
from mdk.types.specifier import TypeSpecifier

__all__ = ['VariableExpression', 'IntVar', 'FloatVar', 'ShortVar', 'ByteVar', 'BoolVar']

class VariableExpression(Expression):
    type: TypeSpecifier
    exprn: str
    def __init__(self, type: TypeSpecifier, scope: StateScope | None = None, system: bool = False) -> None: ...
    def make_expression(self, exprn: str): ...
    def set(self, val: ConvertibleExpression) -> None: ...
    def add(self, val: ConvertibleExpression) -> None: ...

    def __eq__(self, other: ConvertibleExpression) -> Expression: ... # type: ignore
    def __ne__(self, other: ConvertibleExpression) -> Expression: ... # type: ignore
    def __lt__(self, other: ConvertibleExpression) -> Expression: ...
    def __le__(self, other: ConvertibleExpression) -> Expression: ...
    def __gt__(self, other: ConvertibleExpression) -> Expression: ...
    def __ge__(self, other: ConvertibleExpression) -> Expression: ...
    def __add__(self, other: ConvertibleExpression) -> Expression: ...
    def __sub__(self, other: ConvertibleExpression) -> Expression: ...
    def __mul__(self, other: ConvertibleExpression) -> Expression: ...
    def __truediv__(self, other: ConvertibleExpression) -> Expression: ...
    def __floordiv__(self, other: ConvertibleExpression) -> Expression: ...
    def __mod__(self, other: ConvertibleExpression) -> Expression: ...
    def __pow__(self, other: ConvertibleExpression) -> Expression: ...
    def __rshift__(self, other: ConvertibleExpression) -> NoReturn: ...
    def __lshift__(self, other: ConvertibleExpression) -> NoReturn: ...
    def __and__(self, other: ConvertibleExpression) -> Expression: ...
    def __or__(self, other: ConvertibleExpression) -> Expression: ...
    def __xor__(self, other: ConvertibleExpression) -> Expression: ...
    def __radd__(self, other: ConvertibleExpression) -> Expression: ...
    def __rsub__(self, other: ConvertibleExpression) -> Expression: ...
    def __rmul__(self, other: ConvertibleExpression) -> Expression: ...
    def __rtruediv__(self, other: ConvertibleExpression) -> Expression: ...
    def __rfloordiv__(self, other: ConvertibleExpression) -> Expression: ...
    def __rmod__(self, other: ConvertibleExpression) -> Expression: ...
    def __rpow__(self, other: ConvertibleExpression) -> Expression: ...
    def __rlshift__(self, other: ConvertibleExpression) -> NoReturn: ...
    def __rrshift__(self, other: ConvertibleExpression) -> NoReturn: ...
    def __rand__(self, other: ConvertibleExpression) -> Expression: ...
    def __ror__(self, other: ConvertibleExpression) -> Expression: ...
    def __rxor__(self, other: ConvertibleExpression) -> Expression: ...
    def __neg__(self) -> Expression: ...
    def __pos__(self) -> Expression: ...
    def __abs__(self) -> Expression: ...
    def __invert__(self) -> Expression: ...
    def __round__(self) -> Expression: ...
    def __trunc__(self) -> Expression: ...
    def __floor__(self) -> Expression: ...
    def __ceil__(self) -> Expression: ...
    def __bool__(self) -> Literal[True]: ...

class VariableType(Protocol):
    def __call__(self, /, scope: Optional[StateScope] = ..., system: bool = ...) -> VariableExpression:
        ...

IntVar: VariableType
ShortVar: VariableType
ByteVar: VariableType
BoolVar: VariableType
FloatVar: VariableType
