# Copyright (C) MatrixEditor 2023-2025
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
from caterpillar import registry
from caterpillar.abc import (
    _ContextLambda,
    _ContextLike,
    _GreedyType,
    _PrefixedType,
    _StructLike,
    _SwitchLike,
    _IT,
    _OT,
    _LengthT,
    _StructT,
    _OptionLike,
    _EndianLike,
)
from caterpillar.byteorder import (
    Arch,
    ByteOrder,
)
from typing import Any, TypeVar
from typing_extensions import Self

_T = TypeVar("_T")

def singleton(cls: type[_T]) -> _T: ...

INVALID_DEFAULT: object = ...
DEFAULT_OPTION: object = ...

class Field(_StructLike[_IT, _OT]):
    order: _EndianLike
    arch: Arch
    default: _OT | None
    bits: _ContextLambda | int | None
    __name__: str | None
    def __init__(
        self,
        struct: _StructT[_IT, _OT],
        order: _EndianLike | None = None,
        offset: _ContextLambda | int = -1,
        flags: set[_OptionLike] | None = None,
        amount: _ContextLambda | int | _PrefixedType = 0,
        options: _SwitchLike[_OT, Any] | None = None,
        condition: _ContextLambda | bool = True,
        arch: Arch | None = None,
        default: _OT | None = ...,
        bits: _ContextLambda | int | None = None,
    ) -> None: ...
    @property
    def struct(self) -> _StructT[_IT, _OT]: ...
    @struct.setter
    def struct(self, value: _StructT[_IT, _OT]) -> None: ...
    @property
    def condition(self) -> _ContextLambda[bool] | bool: ...
    @condition.setter
    def condition(self, value: _ContextLambda[bool] | bool) -> None: ...
    @property
    def flags(self) -> set[_OptionLike]: ...
    @flags.setter
    def flags(self, value: set[ _OptionLike]) -> None: ...
    def add_flag(self, flag: _OptionLike) -> None: ...
    def has_flag(self, flag: _OptionLike) -> bool: ...
    def remove_flag(self, flag: _OptionLike) -> None: ...
    @property
    def offset(self) -> _ContextLambda[int] | int: ...
    @offset.setter
    def offset(self, value: _ContextLambda[int] | int) -> None: ...
    @property
    def amount(self) -> _LengthT: ...
    @amount.setter
    def amount(self, value: _LengthT) -> None: ...
    @property
    def options(self) -> _SwitchLike[_OT, Any]: ...
    @options.setter
    def options(self, value: _SwitchLike[_OT, Any]) -> None: ...
    def __or__(self, flag: _OptionLike) -> Self: ...
    def __xor__(self, flag: _OptionLike) -> Self: ...
    def __matmul__(self, offset: _ContextLambda | int) -> Self: ...
    def __getitem__(self, dim: _LengthT) -> Self: ...
    def __rshift__(self, switch: _SwitchLike[_IT, _OT]) -> Self: ...
    def __floordiv__(self, condition: _ContextLambda | bool) -> Self: ...
    def __rsub__(self, bits: _ContextLambda | int) -> Self: ...
    def __set_byteorder__(self, order: ByteOrder) -> Self: ...
    def __type__(self) -> type: ...
    def __unpack__(self, context: _ContextLike) -> _OT: ...
    def __pack__(self, obj: _IT, context: _ContextLike) -> None: ...
    def __size__(self, context: _ContextLike) -> int: ...
    __ixor__ = __xor__
    __ior__ = __or__
    __ifloordiv__ = __floordiv__
    __irshift__ = __rshift__
    __imatmul__ = __matmul__
    __isub__ = __rsub__
    def _verify_context_value(self, value: Any, expected: type) -> None: ...
    def is_seq(self) -> bool: ...
    def is_enabled(self, context: _ContextLike) -> bool: ...
    def has_condition(self) -> bool: ...
    def length(self, context: _ContextLike) -> int | _GreedyType | _PrefixedType: ...
    def get_struct(
        self, value: Any, context: _ContextLike
    ) -> _StructLike[_IT, _OT]: ...
    def get_offset(self, context: _ContextLike) -> int: ...
    def get_type(self) -> type: ...
    def get_name(self) -> str | None: ...

class _CallableTypeConverter(registry.TypeConverter):
    def matches(self, annotation: Any) -> bool: ...
    def convert(self, annotation: Any, kwargs: dict) -> Field: ...
