#!/usr/bin/env python3.8
#
# Copyright 2016 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Make a mapping of dependencies for fidl files.

The map contains one line per mapping, each of which is from a fidl file location
to a sequence of GN build targets. If the mapping is public (ie directly from the
source or through a public_deps dependency) then it is prepended with "pub ".

The sequence of targets has length greater than 1 if the file can be referenced
from this module through a sequence of dependencies.

An example entry is:

pub //garnet/public/lib/ui/views/fidl/views.fidl: //garnet/public/lib/media/fidl:services //garnet/public/lib/ui/base_view/cpp:cpp
"""

import ast
import optparse
import os
import sys
import zipfile


# for some reason, gn seems to tack on an extra element in the directory
def fix_label(label):
    split_tag = label.split(':')
    split_label = split_tag[0].split('/')
    split_label.pop()
    split_tag[0] = '/'.join(split_label)
    return ':'.join(split_tag)


def rel_label(label, relpath):
    split_label = label.split(':')[0].split('/')
    for el in relpath.split('/'):
        if el == '..':
            split_label.pop()
        else:
            split_label.append(el)
    return '/'.join(split_label)


def handle_map_deps(o, depsmap, covered, target, is_public):
    #o.write('#pass-through from %s (public %s)\n' % (depsmap, is_public))
    for dep in file(depsmap):
        parts = dep.split()
        if parts[0] != 'pub':
            continue
        fileref = parts[1].rstrip(':')
        if fileref in covered:
            continue
        pubstr = 'pub ' if is_public else ''
        o.write(
            '%s%s: %s %s\n' % (pubstr, fileref, target, ' '.join(parts[2:])))


def make_map(output, sources, map_deps, map_public_deps, target):
    target = fix_label(target)
    o = file(output, 'w')
    covered = set()
    for i in sources:
        covered.add(i)
        new_path = rel_label(target, i)
        o.write('pub %s: %s\n' % (new_path, target))
    for m in map_deps:
        handle_map_deps(o, m, covered, target, False)
    for m in map_public_deps:
        handle_map_deps(o, m, covered, target, True)


def main():
    parser = optparse.OptionParser()

    parser.add_option('--sources', help='List of source files.')
    parser.add_option('--target', help='Name of current target.')
    parser.add_option(
        '--map-deps', help='List of map files of deps to aggregate.')
    parser.add_option(
        '--map-public-deps',
        help='List of map files of public deps to aggregate.')
    parser.add_option('--output', help='Path to output archive.')

    options, _ = parser.parse_args()

    sources = []
    if (options.sources):
        sources = ast.literal_eval(options.sources)
    map_deps = []
    if options.map_deps:
        map_deps = ast.literal_eval(options.map_deps)
    map_public_deps = []
    if options.map_public_deps:
        map_public_deps = ast.literal_eval(options.map_public_deps)
    output = options.output
    target = options.target

    make_map(output, sources, map_deps, map_public_deps, target)


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