import sys
import os
import getopt

sys.path.insert(0, '..')

_ARGS_ARGS_FLAG = 4
_KW_ARGS_FLAG = 8


def find_methods(klass):
    methods = []
    for name, attr in klass.__dict__.iteritems():
        if name.startswith('_'):
            continue
        if callable(attr):
            args = []
            code = attr.func_code
            arg_names = list(code.co_varnames[1:code.co_argcount])
            arg_idx = code.co_argcount
            if code.co_flags & _ARGS_ARGS_FLAG:
                arg_names.append('*' + code.co_varnames[arg_idx])
                arg_idx += 1
            if code.co_flags & _KW_ARGS_FLAG:
                arg_names.append('**' + code.co_varnames[arg_idx])
            methods.append((name, arg_names, klass.__name__))
    for base in klass.__bases__:
        methods.extend(find_methods(base))
    return methods


def combine_methods(methods):
    combined = []
    names = {}
    for name, arg_names, klass in methods:
        if names.get(name):
            continue
        combined.append((name, arg_names, klass))
        names[name] = 1
    combined.sort()
    return combined


def method_table(klass):
    n = find_methods(klass)
    print r'\begin{longtableii}{l|l}{textrm}{Method}{Mixin}'
    for name, arg_names, klass in combine_methods(n):
        args = ', '.join(arg_names)
        print r'\lineii{\method{%s(%s)}}{\class{%s}}' % (name, args, klass)
    print r'\end{longtableii}'


def usage():
    sys.exit('usage: %s [-o filename] module.class'
             % os.path.basename(sys.argv[0]))


if __name__ == '__main__':
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'o:', ['output='])
    except getopt.GetoptError:
        usage()
    for opt, arg in opts:
        if opt in ('-o', '--output'):
            sys.stdout = open(arg, 'w')

    if len(args) != 1:
        usage()
    try:
        mod_name, klass_name = args[0].split('.')
    except:
        usage()

    mod = __import__(mod_name)
    klass = getattr(mod, klass_name)
    method_table(klass)
