# 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 ._base import Field
from caterpillar.abc import (
    _ContextLambda,
    _ContextLike,
    _StructLike,
    _SwitchLike,
    _LengthT,
    _IT,
    _OT,
    _OptionLike,
)
from caterpillar.byteorder import ByteOrder
from typing import (
    Any,
    Callable,
    Collection,
    Dict,
    Generic,
    List,
    Type,
    TypeVar,
    Union,
    overload,
)

_NextOT = TypeVar("_NextOT")

class FieldMixin(Generic[_IT, _OT]):
    def __or__(self, flag: _OptionLike) -> Field[_IT, _OT]: ...
    def __xor__(self, flag: _OptionLike) -> Field[_IT, _OT]: ...
    def __matmul__(self, offset: _ContextLambda | int) -> Field[_IT, _OT]: ...
    def __getitem__(self, dim: _LengthT) -> Field[Collection[_IT], Collection[_OT]]: ...
    def __rshift__(self, switch: _SwitchLike) -> Field[_IT, _OT]: ...
    def __floordiv__(self, condition: _ContextLambda | bool) -> Field[_IT, _OT]: ...
    def __set_byteorder__(self, order: ByteOrder) -> Field[_IT, _OT]: ...
    def __rsub__(self, bits: _ContextLambda | int) -> Field[_IT, _OT]: ...
    def __and__(self, other: _StructLike) -> Chain: ...

class FieldStruct(FieldMixin[_IT, _OT], _StructLike[_IT, _OT]):
    def pack_single(self, obj: _IT, context: _ContextLike) -> None: ...
    def unpack_single(self, context: _ContextLike) -> _OT: ...
    def pack_seq(self, seq: Collection[_IT], context: _ContextLike) -> None: ...
    def unpack_seq(self, context: _ContextLike) -> Collection[_OT]: ...
    def __pack__(self, obj: _IT, context: _ContextLike) -> None: ...
    def __unpack__(self, context: _ContextLike) -> _OT: ...

class Chain(FieldStruct[_IT, _OT]):
    @overload
    def __init__(
        self, initial: _StructLike[_IT, Any], *structs: _StructLike
    ) -> None: ...
    @overload
    def __init__(self, initial: _StructLike[_IT, _OT], *structs: None) -> None: ...
    @property
    def head(self) -> _StructLike[_IT, Any]: ...
    @property
    def tail(self) -> _StructLike[Any, _OT]: ...
    def __size__(self, context: _ContextLike) -> int: ...
    def __type__(self) -> Type[_OT]: ...
    def __and__(self, other: _StructLike[_OT, _NextOT]) -> Chain[_IT, _NextOT]: ...
    def __rand__(self, other: _StructLike[_OT, _NextOT]) -> Chain[_IT, _NextOT]: ...
    def unpack_single(self, context: _ContextLike) -> _OT: ...
    def pack_single(self, obj: _IT, context: _ContextLike) -> None: ...

class Operator:
    func: Callable[[Any, Any], _StructLike]
    def __init__(self, func: Callable[[Any, Any], _StructLike]) -> None: ...
    def __truediv__(self, arg2) -> _StructLike: ...
    def __rtruediv__(self, arg1) -> Operator: ...
    def __call__(self, arg1, arg2) -> _StructLike: ...

def get_args(
    args: Union[Any, _ContextLambda, List[Union[Any, _ContextLambda]]],
    context: _ContextLike,
) -> list[Any]: ...
def get_kwargs(
    kwargs: Dict[Any, Union[Any, _ContextLambda]], context: _ContextLike
) -> dict: ...
