import random
from collections.abc import Callable, Iterable
from typing import TypeVar, overload

from .decorator import make_data_last

T = TypeVar('T')


@overload
def shuffle(iterable: Iterable[T], /) -> list[T]: ...


@overload
def shuffle() -> Callable[[Iterable[T]], list[T]]: ...


@make_data_last
def shuffle(iterable: Iterable[T], /) -> list[T]:
    """
    Returns the elements of the iterable in random order.

    Parameters
    ----------
    iterable : Iterable[T]
        Iterable to shuffle (positional-only).

    Returns
    -------
    list[T]
        List of the elements in the iterable in random order.

    Examples
    --------
    Data first:
    >>> import random; random.seed(0)
    >>> R.shuffle([4, 2, 7, 5])
    [7, 4, 2, 5]

    Data last:
    >>> R.pipe([4, 2, 7, 5], R.shuffle())
    [4, 2, 5, 7]
    >>> R.shuffle()(range(1, 5))
    [1, 3, 2, 4]

    """
    iterable = list(iterable)
    random.shuffle(iterable)
    return iterable
