#!/usr/bin/env python

from collections import defaultdict
from optparse import OptionParser
import re
import sys


class Type(object):

    def __init__(self, name, members=None):
        self.name = name
        self.namespace = '.'.join(self.name.split('.')[:-1]) or None
        self.members = members or {}

    def extern(self):
        lines = []
        lines.append('/**\n')
        lines.append(' * @interface\n')
        lines.append(' */\n')
        lines.append('%s = function() {};\n' % (self.name,))
        for key in sorted(self.members.keys()):
            lines.append('\n')
            lines.append('\n')
            lines.append('/**\n')
            lines.append(' * @type {%s}\n' % (self.members[key],))
            lines.append(' */\n')
            lines.append('%s.prototype.%s;\n' % (self.name, key))
        return ''.join(lines)

    def provide(self):
        return 'goog.provide(\'%sType\');\n' % (self.name,)

    def typedef(self):
        lines = []
        lines.append('/**\n')
        for i, key in enumerate(sorted(self.members.keys())):
            prefix =  ' * @typedef {{' if i == 0 else ' *            '
            suffix = '}}' if i == len(self.members) - 1 else ','
            type = self.members[key]
            if '|' in type:
                type = '(%s)' % (type,)
            lines.append('%s%s: %s%s\n' % (prefix, key, type, suffix))
        lines.append(' */\n')
        lines.append('%s;\n' % (self.name,))
        return ''.join(lines)


def main(argv):

    option_parser = OptionParser()
    options, args = option_parser.parse_args(argv[1:])

    requires = set()
    symbols = set()
    properties = defaultdict(set)
    for arg in args:
        for line in open(arg):
            line = line.strip()
            if not line:
                continue
            m = re.match('@exportSymbol\s*(?P<symbol>\S+)\Z', line)
            if m:
                requires.add(m.group('symbol'))
                symbols.add(m.group('symbol'))
                continue
            m = re.match('@exportProperty\s*(?P<property>\S+)\Z', line)
            if m:
                components = m.group('property').split('.')
                if components[-2] == 'prototype':
                    requires.add('.'.join(components[:-2]))
                else:
                    requires.add('.'.join(components[:-1]))
                properties['.'.join(components[:-1])].add(components[-1])
                continue
            raise RuntimeError(line)

    if requires:
        for require in sorted(requires):
            sys.stdout.write('goog.require(\'%s\');\n' % (require,))
        sys.stdout.write('\n\n')
    for i, obj in enumerate(sorted(symbols | set(properties.keys()))):
        if i:
            sys.stdout.write('\n')
        if obj in symbols:
            sys.stdout.write('goog.exportSymbol(\n    \'%s\',\n    %s);\n' % (obj, obj))
        for prop in properties[obj]:
            sys.stdout.write('goog.exportProperty(\n    %s,\n    \'%s\',\n    %s.%s);\n' % (obj, prop, obj, prop))


if __name__ == '__main__':
    sys.exit(main(sys.argv))
