from typing import Union
from typing import Dict
from typing import List
from typing import Tuple
from typing import Set


def to_lowercase(d: Union[Dict, List, Tuple, Set, str]) -> Union[Dict, List, Tuple, Set, str]:
    """Convert an object to lowercase. All keys and values in a dictionary will be converted
    to lowercase as will all objects in a list, tuple or set.

    Based on the answer https://stackoverflow.com/a/40789531/1303032

    Args:
        d: Object to lower case
    Returns:
        dict: Dictionary of lower case keys and values
    """
    if isinstance(d, dict):
        return {k.lower(): to_lowercase(v) for k, v in d.items()}
    elif isinstance(d, (list, set, tuple)):
        t = type(d)
        return t(to_lowercase(o) for o in d)
    elif isinstance(d, str):
        return d.lower()
    else:
        return d