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

from .decorator import make_data_last

T = TypeVar('T')


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


@overload
def sample(size: int, /) -> Callable[[Iterable[T]], list[T]]: ...


@make_data_last
def sample(iterable: Iterable[T], size: int, /) -> list[T]:
    """
    Returns a random sample of size given from the iterable.

    Parameters
    ----------
    iterable : Iterable[T]
        Iterable to sample from (positional-only).
    size: int
        Size of the sample (positional-only).

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

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

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

    """
    return random.sample(list(iterable), size)
