# Copyright 2023 by Armoha.
# All rights reserved.
# This file is part of EUD python library (eudplib),
# and is released under "MIT License Agreement". Please see the LICENSE
# file that should have been included as part of this package.

from collections.abc import Callable, Iterator
from typing import TYPE_CHECKING, Any, TypeGuard

from typing_extensions import Self

if TYPE_CHECKING:
    from ...utils import ExprProxy

class ObjAllocator:
    def WriteByte(self, number: int) -> None: ...  # noqa: N802
    def WriteWord(self, number: int) -> None: ...  # noqa: N802
    def WriteDword(self, number) -> None: ...  # noqa: N802
    def WritePack(self, structformat: str, _arglist: list) -> None: ...  # noqa: N802
    def WriteBytes(self, b: bytes) -> None: ...  # noqa: N802
    def WriteSpace(self, ssize: int) -> None: ...  # noqa: N802
    def _write_trigger(self, conditions: int, actions: int) -> None: ...

class PayloadBuffer:
    def WriteByte(self, number: int) -> None: ...  # noqa: N802
    def WriteWord(self, number: int) -> None: ...  # noqa: N802
    def WriteDword(self, number) -> None: ...  # noqa: N802
    def WritePack(self, structformat: str, _arglist: list) -> None: ...  # noqa: N802
    def WriteBytes(self, b: bytes) -> None: ...  # noqa: N802
    def WriteSpace(self, ssize: int) -> None: ...  # noqa: N802
    def _write_trigger(
        self, prevptr, nextptr, conditions: Iterator, actions: Iterator, flags
    ) -> None: ...

class PayloadBuilder:
    def __new__(cls) -> Self: ...
    def alloc_objects(self, found_objects: dict) -> None: ...
    def construct_payload(
        self, found_objects: dict
    ) -> tuple[bytes, list[int], list[int]]: ...
    def register_create_payload_callback(self, f: Callable[[], Any]) -> None: ...
    def register_after_collecting_callback(self, f: Callable[[], Any]) -> None: ...
    def call_callbacks_on_create_payload(self) -> None: ...
    def call_callbacks_after_collecting(self) -> None: ...
    def get_object_addr(self, index: int) -> RlocInt_C: ...

class RlocInt_C:  # noqa: N801
    def __new__(cls, offset: int, rlocmode: int) -> Self: ...
    @property
    def offset(self) -> int: ...
    @property
    def rlocmode(self) -> int: ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...
    def __add__(self, rhs: RlocInt_C | int) -> RlocInt_C: ...
    def __radd__(self, rhs: RlocInt_C | int) -> RlocInt_C: ...
    def __sub__(self, rhs: RlocInt_C | int) -> RlocInt_C: ...
    def __rsub__(self, rhs: RlocInt_C | int) -> RlocInt_C: ...
    def __mul__(self, rhs: RlocInt_C | int) -> RlocInt_C: ...
    def __rmul__(self, rhs: RlocInt_C | int) -> RlocInt_C: ...
    def __floordiv__(self, rhs: RlocInt_C | int) -> RlocInt_C: ...
    def __and__(self, rhs: RlocInt_C | int) -> RlocInt_C: ...
    def __rand__(self, rhs: RlocInt_C | int) -> RlocInt_C: ...
    def __or__(self, rhs: RlocInt_C | int) -> RlocInt_C: ...
    def __ror__(self, rhs: RlocInt_C | int) -> RlocInt_C: ...
    def __invert__(self) -> RlocInt_C: ...
    def __neg__(self) -> RlocInt_C: ...
    def _is_aligned_ptr(self) -> bool: ...
    def _is_ptr(self) -> bool: ...
    def _is_epd(self) -> bool: ...

def RlocInt(offset: int, rlocmode: int) -> RlocInt_C: ...  # noqa: N802
def toRlocInt(x: RlocInt_C | int) -> RlocInt_C: ...  # noqa: N802

class ConstExpr:
    def __new__(cls, baseobj, offset: int = 0, rlocmode: int = 4) -> Self: ...
    # def __init__(self) -> None: ...
    def Evaluate(self) -> RlocInt_C: ...  # noqa: N802
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...
    def __int__(self) -> int: ...
    def __add__(self, rhs: int) -> ConstExpr: ...
    def __radd__(self, rhs: int) -> ConstExpr: ...
    def __sub__(self, rhs: int) -> ConstExpr: ...
    def __rsub__(self, rhs: int) -> ConstExpr: ...
    def __mul__(self, rhs: int) -> ConstExpr: ...
    def __rmul__(self, rhs: int) -> ConstExpr: ...
    def __floordiv__(self, rhs: int) -> ConstExpr: ...
    def __mod__(self, rhs: int) -> int: ...
    def __divmod__(self, rhs: int) -> tuple[ConstExpr, int]: ...
    def __neg__(self) -> ConstExpr: ...
    def _is_aligned_ptr(self) -> bool: ...
    def _is_epd(self) -> bool: ...

class Forward(ConstExpr):
    expr: Any
    def __new__(cls) -> Self: ...
    def __lshift__(self, expr: Any) -> Any: ...
    def IsSet(self) -> bool: ...  # noqa: N802
    def Reset(self) -> None: ...  # noqa: N802
    def Evaluate(self) -> RlocInt_C: ...  # noqa: N802
    def __call__(self, *args: Any, **kwds: Any) -> Any: ...
    def __getattr__(self, name: str) -> Any: ...
    def __getitem__(self, name: Any) -> Any: ...
    def __setitem__(self, name: Any, newvalue: Any) -> None: ...

def Evaluate(x: Any) -> RlocInt_C: ...  # noqa: N802
def IsConstExpr(  # noqa: N802
    x: Any,
) -> TypeGuard[int | ConstExpr | ExprProxy[int] | ExprProxy[ConstExpr]]: ...
