from collections.abc import Callable
from typing import overload

import remedapy as R
from remedapy.decorator import make_data_last


@overload
def to_title_case(s: str, /, *, preserve_consecutive_uppercase: bool = True) -> str: ...


@overload
def to_title_case(*, preserve_consecutive_uppercase: bool = True) -> Callable[[str], str]: ...


@make_data_last
def to_title_case(s: str, /, *, preserve_consecutive_uppercase: bool = True) -> str:
    """
    Makes the string title case - words are spaced, every word capitalised.

    Parameters
    ----------
    s : str
        String to title case (positional-only).
    preserve_consecutive_uppercase: bool
        Whether to not change words made of consecutive uppercase letters. Default: True.

    Returns
    -------
    str
        Title cased string.

    Examples
    --------
    Data first:
    >>> R.to_title_case('hello world')
    'Hello World'
    >>> R.to_title_case('--foo-bar--')
    'Foo Bar'
    >>> R.to_title_case('fooBar')
    'Foo Bar'
    >>> R.to_title_case('__FOO_BAR__')
    'Foo Bar'
    >>> R.to_title_case('XMLHttpRequest')
    'XML Http Request'
    >>> R.to_title_case('XMLHttpRequest', preserve_consecutive_uppercase=False)
    'Xml Http Request'

    Data last:
    >>> R.to_title_case()('hello world')
    'Hello World'
    >>> R.to_title_case()('--foo-bar--')
    'Foo Bar'
    >>> R.to_title_case()('fooBar')
    'Foo Bar'
    >>> R.to_title_case()('__FOO_BAR__')
    'Foo Bar'
    >>> R.to_title_case()('XMLHttpRequest')
    'XML Http Request'
    >>> R.to_title_case(preserve_consecutive_uppercase=False)('XMLHttpRequest')
    'Xml Http Request'

    """
    return R.pipe(
        s,
        R.when(lambda x: all(not x.islower() for x in x), R.to_lower_case),
        R.to_words,
        R.when(lambda _: not preserve_consecutive_uppercase, R.map(R.to_lower_case)),
        R.map(R.capitalise),
        R.join(' '),
    )
