# Copyright 2015 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Buildgen expand filegroups plugin.

This takes the list of libs from our yaml dictionary,
and expands any and all filegroup.

"""


def excluded(filename, exclude_res):
    for r in exclude_res:
        if r.search(filename):
            return True
    return False


def uniquify(lst):
    out = []
    for el in lst:
        if el not in out:
            out.append(el)
    return out


FILEGROUP_LISTS = ['src', 'headers', 'public_headers', 'deps']

FILEGROUP_DEFAULTS = {
    'language': 'c',
    'boringssl': False,
    'zlib': False,
    'ares': False,
}


def mako_plugin(dictionary):
    """The exported plugin code for expand_filegroups.

  The list of libs in the build.yaml file can contain "filegroups" tags.
  These refer to the filegroups in the root object. We will expand and
  merge filegroups on the src, headers and public_headers properties.

  """
    libs = dictionary.get('libs')
    targets = dictionary.get('targets')
    filegroups_list = dictionary.get('filegroups')
    filegroups = {}

    for fg in filegroups_list:
        for lst in FILEGROUP_LISTS:
            fg[lst] = fg.get(lst, [])
            fg['own_%s' % lst] = list(fg[lst])
        for attr, val in FILEGROUP_DEFAULTS.iteritems():
            if attr not in fg:
                fg[attr] = val

    todo = list(filegroups_list)
    skips = 0

    while todo:
        assert skips != len(
            todo), "infinite loop in filegroup uses clauses: %r" % [
                t['name'] for t in todo
            ]
        # take the first element of the todo list
        cur = todo[0]
        todo = todo[1:]
        # check all uses filegroups are present (if no, skip and come back later)
        skip = False
        for uses in cur.get('uses', []):
            if uses not in filegroups:
                skip = True
        if skip:
            skips += 1
            todo.append(cur)
        else:
            skips = 0
            assert 'plugins' not in cur
            plugins = []
            for uses in cur.get('uses', []):
                for plugin in filegroups[uses]['plugins']:
                    if plugin not in plugins:
                        plugins.append(plugin)
                for lst in FILEGROUP_LISTS:
                    vals = cur.get(lst, [])
                    vals.extend(filegroups[uses].get(lst, []))
                    cur[lst] = vals
            cur_plugin_name = cur.get('plugin')
            if cur_plugin_name:
                plugins.append(cur_plugin_name)
            cur['plugins'] = plugins
            filegroups[cur['name']] = cur

    # build reverse dependency map
    things = {}
    for thing in dictionary['libs'] + dictionary['targets'] + dictionary['filegroups']:
        things[thing['name']] = thing
        thing['used_by'] = []
    thing_deps = lambda t: t.get('uses', []) + t.get('filegroups', []) + t.get('deps', [])
    for thing in things.itervalues():
        done = set()
        todo = thing_deps(thing)
        while todo:
            cur = todo[0]
            todo = todo[1:]
            if cur in done: continue
            things[cur]['used_by'].append(thing['name'])
            todo.extend(thing_deps(things[cur]))
            done.add(cur)

    # the above expansion can introduce duplicate filenames: contract them here
    for fg in filegroups.itervalues():
        for lst in FILEGROUP_LISTS:
            fg[lst] = uniquify(fg.get(lst, []))

    for tgt in dictionary['targets']:
        for lst in FILEGROUP_LISTS:
            tgt[lst] = tgt.get(lst, [])
            tgt['own_%s' % lst] = list(tgt[lst])

    for lib in libs + targets:
        assert 'plugins' not in lib
        plugins = []
        for lst in FILEGROUP_LISTS:
            vals = lib.get(lst, [])
            lib[lst] = list(vals)
            lib['own_%s' % lst] = list(vals)
        for fg_name in lib.get('filegroups', []):
            fg = filegroups[fg_name]
            for plugin in fg['plugins']:
                if plugin not in plugins:
                    plugins.append(plugin)
            for lst in FILEGROUP_LISTS:
                vals = lib.get(lst, [])
                vals.extend(fg.get(lst, []))
                lib[lst] = vals
            lib['plugins'] = plugins
        if lib.get('generate_plugin_registry', False):
            lib['src'].append(
                'src/core/plugin_registry/%s_plugin_registry.cc' % lib['name'])
        for lst in FILEGROUP_LISTS:
            lib[lst] = uniquify(lib.get(lst, []))
