from __future__ import unicode_literals

import inspect
from rpc.decorators import api_manager


class ApiInfo(object):

    @classmethod
    def get_method_list(cls):
        return api_manager.get_method_list()

    @classmethod
    def get_method_document(cls, name):
        info = api_manager.get_method_info(name)
        if info is None:
            return None
        assert name == info.name
        if inspect.isfunction(info.func):
            return cls.get_method_function_document(info)

    @classmethod
    def get_method_function_document(cls, method_info):
        members = dict(inspect.getmembers(method_info.func))
        __doc__ = members['__doc__']

        return {
            '__doc__': __doc__,
            'arg_spec': cls.parse_argspec(method_info),
            'path': ':'.join([method_info.func.__module__, method_info.func.__name__])
        }

    @classmethod
    def parse_argspec(cls, method_info):
        arg_spec = inspect.getargspec(method_info.func)
        args = arg_spec.args
        varargs = arg_spec.varargs
        keywords = arg_spec.keywords
        defaults = arg_spec.defaults

        if defaults is None:
            defaults = []
        else:
            defaults = list(defaults)
        assert len(args) >= len(defaults)

        if method_info.options['with_context']:
            args = args[1:]
        required = [False for _ in defaults]
        while len(args) > len(defaults):
            defaults.insert(0, None)
            required.insert(0, True)
        return [
            dict(name=name, default=default, required=required)
            for name, default, required in sorted(zip(args, defaults, required))
        ]

api_info = ApiInfo()
