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

from remedapy.decorator import make_data_last

Key = str | int
T = TypeVar('T')


@overload
def swap_props(data: dict[Key, T], prop1: Key, prop2: Key, /) -> dict[Key, T]: ...


@overload
def swap_props(prop1: Key, prop2: Key, /) -> Callable[[dict[Key, T]], dict[Key, T]]: ...


@make_data_last
def swap_props(data: dict[Key, T], prop1: Key, prop2: Key, /) -> dict[Key, T]:
    """
    Returns a dict with the values of the given properties swapped.

    Parameters
    ----------
    data : dict[Key, T]
        Dict to swap properties in (positional-only).
    prop1 : Key
        First property to swap (positional-only).
    prop2 : Key
        Second property to swap (positional-only).

    Returns
    -------
    dict[Key, T]
        Dict with the values of the given properties swapped.

    See Also
    --------
    swap_indices

    Examples
    --------
    Data first:
    >>> R.swap_props({'a': 1, 'b': 2, 'c': 3}, 'a', 'b')
    {'a': 2, 'b': 1, 'c': 3}

    Data last:
    >>> R.swap_props('a', 'b')({'a': 1, 'b': 2, 'c': 3})
    {'a': 2, 'b': 1, 'c': 3}

    """
    # TODO: generic swap
    return data | {prop1: data[prop2], prop2: data[prop1]}
