import inspect
import functools
import logging


def deprecated(substitution):
    """This is a decorator which can be used to mark functions or classes
    as deprecated. It will result in a warning being emmitted
    when the function/class is used."""

    cls_warn = "Call to deprecated class `{name}`. "
    func_warn = "Call to deprecated function `{name}`. "
    if isinstance(substitution, str):

        def decorator(func):
            warn_info = cls_warn if inspect.isclass(func) else func_warn
            warn_info += "Please use `{substitution}` instead."

            @functools.wraps(func)
            def new_func(*args, **kwargs):
                logging.warning(warn_info.format(name=func.__name__, substitution=substitution))
                return func(*args, **kwargs)

            return new_func

        return decorator

    elif inspect.isclass(substitution) or inspect.isfunction(substitution):
        func = substitution
        warn_info = cls_warn if inspect.isclass(func) else func_warn

        @functools.wraps(func)
        def new_func(*args, **kwargs):
            logging.warning(warn_info.format(name=func.__name__))
            return func(*args, **kwargs)

        return new_func

    else:
        raise TypeError(repr(type(substitution)))