import inspect


def listens_to(name):  # noqa: D401
    """Decorator to register a method of a :class:`Handler` as a listener.

    The method must be a coroutine.

    Arguments
    ---------
    name: :class:`str`
        The name of the event to listen to.

    Raises
    ------
    TypeError
        The name was not a string or the method was not a coroutine.
    """
    if not isinstance(name, str):
        raise TypeError("Name must be str, got {0.__class__.__name__} instead.".format(name))

    def wrapper(func):
        actual = func
        if isinstance(actual, staticmethod):
            actual = func.__func__

        if not inspect.iscoroutinefunction(actual):
            raise TypeError("Callback must be a coroutine.")

        actual.__shinkei_listens_to__ = name

        return func

    return wrapper