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

from remedapy.decorator import make_data_last

T = TypeVar('T')
V = TypeVar('V')


@overload
def values(source: dict[Any, T] | Iterable[T], /) -> Iterable[T]: ...


@overload
def values() -> Callable[[dict[Any, T] | Iterable[T]], Iterable[T]]: ...


@make_data_last
def values(
    source: dict[Any, T] | Iterable[T],
    /,
) -> Iterable[T]:
    """
    Given an iterable or dict yields its values.

    Parameters
    ----------
    source: dict[Any, T] | Iterable[T]
        Iterable or dict (positional-only).

    Yields
    ------
    T
        The values.

    Examples
    --------
    Data first:
    >>> list(R.values(['x', 'y', 'z']))
    ['x', 'y', 'z']
    >>> list(R.values({'a': 'x', 'b': 'y', 'c': 'z'}))
    ['x', 'y', 'z']

    Data last:
    >>> R.pipe(['x', 'y', 'z'], R.values(), list)
    ['x', 'y', 'z']
    >>> R.pipe({'a': 'x', 'b': 'y', 'c': 'z'}, R.values(), list)
    ['x', 'y', 'z']
    >>> R.pipe({'a': 'x', 'b': 'y', 'c': 'z'}, R.values(), R.first())
    'x'

    """
    if isinstance(source, dict):
        yield from source.values()
    else:
        yield from source
