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

from .decorator import make_data_last

if TYPE_CHECKING:
    from _typeshed import SupportsRichComparison

T = TypeVar('T')


@overload
def sort(iterable: Iterable[T], function: Callable[[T], 'SupportsRichComparison'], /) -> list[T]: ...


@overload
def sort(function: Callable[[T], 'SupportsRichComparison'], /) -> Callable[[Iterable[T]], list[T]]: ...


@make_data_last
def sort(iterable: Iterable[T], function: Callable[[T], 'SupportsRichComparison'], /) -> list[T]:
    """
    Given an iterable and a function, returns a list of the elements of the iterable sorted by the function.

    Alias to sorted(it, key=fn).

    Parameters
    ----------
    iterable : Iterable[T]
        Iterable to sort (positional-only).
    function: Callable[[T], 'SupportsRichComparison']
        Function to use for sorting (positional-only).

    Returns
    -------
    list[T]
        List of the elements in the iterable sorted by the function.

    Examples
    --------
    Data first:
    >>> R.sort([{'a': 1}, {'a': 3}, {'a': 7}, {'a': 2}], R.prop('a'))
    [{'a': 1}, {'a': 2}, {'a': 3}, {'a': 7}]

    Data last:
    >>> R.pipe([{'a': 1}, {'a': 3}, {'a': 7}, {'a': 2}], R.sort(R.prop('a')))
    [{'a': 1}, {'a': 2}, {'a': 3}, {'a': 7}]

    """
    return sorted(iterable, key=function)
