from collections.abc import Callable, Iterable, Sequence
from typing import Any, TypeGuard, TypeVar, overload

from remedapy.decorator import make_data_last

T = TypeVar('T')


@overload
def is_sequence() -> Callable[[Any], TypeGuard[Sequence[Any]]]: ...


@overload
def is_sequence(data: Iterable[T], /) -> TypeGuard[Sequence[T]]: ...


@overload
def is_sequence(data: Any, /) -> TypeGuard[Sequence[Any]]: ...


@make_data_last
def is_sequence(value: Any, /) -> TypeGuard[Sequence[Any]]:
    """
    A function that checks if the passed parameter is a sequence and narrows its type accordingly.

    Alias to `isinstance(value, Sequence).` with `Sequence` from `collections.abc`.

    Parameters
    ----------
    value: Any
        Value to check.

    Returns
    -------
    result: bool
        Whether the value passed is a sequence.

    Examples
    --------
    Data first:
    >>> R.is_sequence([1,2])
    True
    >>> R.is_sequence((x for x in range(3)))
    False

    Data last:
    >>> R.is_sequence()([1,2])
    True
    >>> R.is_sequence()(range(3))
    True

    """
    return isinstance(value, Sequence)
