#!/usr/bin/env python3.8
# Copyright 2018 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.

import argparse
import json
import os
import sys


class Source(object):

    def __init__(self, name, path, file):
        self.name = name
        self.path = path
        self.file = file

    def __str__(self):
        return '%s[%s]' % (self.name, self.path)

    def __hash__(self):
        return hash((self.name, self.path))

    def __eq__(self, other):
        return self.name == other.name and self.path == other.path


def get_sources(dep_files, extra_sources=None):
    # Aggregate source data from dependencies.
    sources = set()
    if extra_sources:
        sources.update(extra_sources)
    for dep in dep_files:
        with open(dep, 'r') as dep_file:
            for name, path in json.load(dep_file).items():
                sources.add(Source(name, path, dep))

    # Verify duplicates.
    sources_by_name = {}
    for src in sources:
        sources_by_name.setdefault(src.name, []).append(src)
    for name, srcs in sources_by_name.items():
        if len(srcs) <= 1:
            continue
        print('Error: source "%s" has multiple paths.' % name)
        for src in srcs:
            print(' - %s (%s)' % (src.path, src.file))
        raise Exception('Could not aggregate sources')

    return {s.name: s.path for s in sources}


def main():
    parser = argparse.ArgumentParser()
    name_group = parser.add_mutually_exclusive_group(required=True)
    name_group.add_argument('--name', help='Name of the current library')
    name_group.add_argument(
        '--name-file',
        help='Path to a file containing the name of the current library')
    parser.add_argument(
        '--source-dir',
        help='Path to the library\'s source directory',
        required=True)
    sources_group = parser.add_mutually_exclusive_group(required=True)
    sources_group.add_argument(
        '--sources', help='List of source files', nargs='*')
    sources_group.add_argument(
        '--allow-globbing',
        action='store_true',
        help='Allow globbing the entire source directory')
    parser.add_argument(
        '--output', help='Path to the file to generate', required=True)
    parser.add_argument(
        '--deps', help='Dependencies of the current library', nargs='*')
    args = parser.parse_args()
    if args.name:
        name = args.name
    elif args.name_file:
        with open(args.name_file, 'r') as name_file:
            name = name_file.read()

    current_sources = []
    if args.sources:
        # TODO(fxbug.dev/3037): verify that the sources are in a single folder.
        for source in args.sources:
            current_sources.append(
                Source(
                    os.path.join(name, source),
                    os.path.join(args.source_dir, source), args.output))
    elif args.allow_globbing:
        current_sources.append(Source(name, args.source_dir, args.output))
    result = get_sources(args.deps, extra_sources=current_sources)
    with open(args.output, 'w') as output_file:
        json.dump(result, output_file, indent=2, sort_keys=True)


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