#!/usr/bin/env python
# Copyright 2017 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.

from collections import namedtuple
import argparse
import os
import errno
import fnmatch
import shlex
import shutil
import sys


manifest_entry = namedtuple('manifest_entry', [
    'group',
    'target',
    'source',
    'manifest',
])


def format_manifest_entry(entry):
    return (('' if entry.group is None else '{' + entry.group + '}') +
            entry.target + '=' + entry.source)


def format_manifest_file(manifest):
    return ''.join(format_manifest_entry(entry) + '\n' for entry in manifest)


def read_manifest_lines(sep, lines, title, manifest_cwd, result_cwd):
    for line in lines:
        # Remove the trailing newline.
        assert line.endswith('\n'), 'Unterminated manifest line: %r' % line
        line = line[:-1]

        # Grok {group}... syntax.
        group = None
        if line.startswith('{'):
            end = line.find('}')
            assert end > 0, 'Unterminated { in manifest line: %r' % line
            group = line[1:end]
            line = line[end + 1:]

        # Grok target=source syntax.
        [target_file, build_file] = line.split(sep, 1)

        if manifest_cwd != result_cwd:
            # Expand the path based on the cwd presumed in the manifest.
            build_file = os.path.normpath(os.path.join(manifest_cwd,
                                                       build_file))
            # Make it relative to the cwd we want to work from.
            build_file = os.path.relpath(build_file, result_cwd)

        # TODO(mcgrathr): Dismal kludge to avoid pulling in asan runtime
        # libraries from the zircon ulib bootfs.manifest because their source
        # file names don't match the ones in the toolchain manifest.
        if 'prebuilt/downloads/clang/lib/' in build_file:
            continue

        yield manifest_entry(group, target_file, build_file, title)


def partition_manifest(manifest, select, selected_group, unselected_group):
    selected = []
    unselected = []
    for entry in manifest:
        if select(entry.group):
            selected.append(entry._replace(group=selected_group))
        else:
            unselected.append(entry._replace(group=unselected_group))
    return selected, unselected


def ingest_manifest_lines(sep, lines, title, in_cwd, groups, out_cwd, output_group):
    groups_seen = set()
    def select(group):
        groups_seen.add(group)
        if isinstance(groups, bool):
            return groups
        return group in groups
    selected, unselected = partition_manifest(
        read_manifest_lines(sep, lines, title, in_cwd, out_cwd),
        select, output_group, None)
    return selected, unselected, groups_seen


def apply_source_rewrites(rewrites, entry):
    for rewrite in rewrites:
        if entry.source == rewrite.source:
            return entry._replace(source=rewrite.target)
    return entry


def apply_rewrites(sep, rewrites, entry):
    for pattern, line in rewrites:
        if fnmatch.fnmatchcase(entry.target, pattern):
            [new_entry] = read_manifest_lines(
                sep,
                [line.format(**entry._asdict()) + '\n'], entry.manifest,
                os.path.dirname(entry.manifest),
                os.path.dirname(entry.manifest))
            entry = new_entry._replace(group=entry.group)
    return entry


def contents_entry(entry):
    with open(entry.source) as file:
        [line] = file.read().splitlines()
        return entry._replace(source=line)


class input_action_base(argparse.Action):
    def __init__(self, *args, **kwargs):
        super(input_action_base, self).__init__(*args, **kwargs)

    def __call__(self, parser, namespace, values, option_string=None):
        outputs = getattr(namespace, 'output', None)

        all_selected = getattr(namespace, 'selected', None)
        if all_selected is None:
            all_selected = []
            setattr(namespace, 'selected', all_selected)
        all_unselected = getattr(namespace, 'unselected', None)
        if all_unselected is None:
            all_unselected = []
            setattr(namespace, 'unselected', all_unselected)

        if namespace.groups is None or outputs is None:
            groups = False
        elif namespace.groups == 'all':
            groups = True
        else:
            groups = set(group if group else None
                         for group in namespace.groups.split(','))

        cwd = getattr(namespace, 'cwd', '')

        if outputs is not None:
            output_group = len(outputs) - 1
        else:
            output_group = None

        selected, unselected, groups_seen = self.get_manifest_lines(
            namespace, values, cwd, groups, namespace.output_cwd, output_group)

        include = getattr(namespace, 'include', [])
        include_source = getattr(namespace, 'include_source', [])
        exclude = getattr(namespace, 'exclude', [])
        if include or exclude or include_source:
            def included(entry):
                def matches(file, patterns):
                    return any(fnmatch.fnmatch(file, pattern)
                               for pattern in patterns)
                if matches(entry.target, exclude):
                    return False
                if include and not matches(entry.target, include):
                    return False
                return (not include_source or
                        matches(entry.source, include_source))
            unselected += filter(lambda entry: not included(entry), selected)
            selected = filter(included, selected)

        if getattr(namespace, 'contents', False):
            selected = map(contents_entry, selected);
            unselected = map(contents_entry, unselected);

        sep = getattr(namespace, 'separator', '=')
        rewrites = [entry.split('=', 1)
                     for entry in getattr(namespace, 'rewrite', [])]
        selected = [apply_rewrites(sep, rewrites, entry) for entry in selected]
        unselected = [apply_rewrites(sep, rewrites, entry) for entry in unselected]

        if not isinstance(groups, bool):
            unused_groups = groups - groups_seen - set([None])
            if unused_groups:
                raise Exception(
                    '%s not found in %r; try one of: %s' %
                    (', '.join(map(repr, unused_groups)), values,
                     ', '.join(map(repr, groups_seen - groups))))

        all_selected += selected
        all_unselected += unselected


class input_manifest_action(input_action_base):
    def __init__(self, *args, **kwargs):
        super(input_manifest_action, self).__init__(*args, **kwargs)

    def get_manifest_lines(self, namespace, filename, *args):
        all_inputs = getattr(namespace, 'manifest', None)
        if all_inputs is None:
            all_inputs = []
            setattr(namespace, 'manifest', all_inputs)
        all_inputs.append(filename)
        with open(filename, 'r') as file:
            return ingest_manifest_lines(getattr(namespace, 'separator', '='),
                                         file, file.name, *args)


class input_entry_action(input_action_base):
    def __init__(self, *args, **kwargs):
        super(input_entry_action, self).__init__(*args, **kwargs)

    def get_manifest_lines(self, namespace, entry, *args):
        return ingest_manifest_lines(
            getattr(namespace, 'separator', '='),
            [entry + '\n'], namespace.entry_manifest, *args)


def common_parse_args(parser):
    parser.fromfile_prefix_chars='@'
    parser.convert_arg_line_to_args = shlex.split
    parser.add_argument('--output', action='append', required=True,
                        metavar='FILE',
                        help='Output file')
    parser.add_argument('--output-cwd', default='',
                        metavar='DIRECTORY',
                        help='Emit source paths relative to DIRECTORY')
    parser.add_argument('--absolute', action='store_true', default=False,
                        help='Output source file names as absolute paths')
    parser.add_argument('--cwd', default='',
                        metavar='DIRECTORY',
                        help='Input entries are relative to this directory')
    parser.add_argument('--groups', default='all',
                        metavar='GROUP_LIST',
                        help='"all" or comma-separated groups to include')
    parser.add_argument('--manifest', action=input_manifest_action,
                        metavar='FILE', default=[],
                        help='Input manifest file (must exist)')
    parser.add_argument('--entry', action=input_entry_action,
                        metavar='PATH=FILE',
                        help='Add a single entry as if from an input manifest')
    parser.add_argument('--entry-manifest', default='<command-line --entry>',
                        metavar='TITLE',
                        help=('Title in lieu of manifest file name for' +
                              ' subsequent --entry arguments'))
    parser.add_argument('--include', action='append', default=[],
                        metavar='TARGET',
                        help='Include only input entries matching TARGET'),
    parser.add_argument('--include-source', action='append', default=[],
                        metavar='SOURCE',
                        help='Include only input entries matching SOURCE'),
    parser.add_argument('--reset-include',
                        action='store_const', const=[], dest='include',
                        help='Reset previous --include')
    parser.add_argument('--exclude', action='append', default=[],
                        metavar='TARGET',
                        help='Ignore input entries matching TARGET'),
    parser.add_argument('--reset-exclude',
                        action='store_const', const=[], dest='exclude',
                        help='Reset previous --exclude')
    parser.add_argument('--separator', default='=',
                        metavar='SEP',
                        help='Use SEP between TARGET and SOURCE in entries')
    return parser.parse_args()


def parse_args():
    parser = argparse.ArgumentParser(description='Read manifest files.')
    parser.add_argument('--copy-contentaddr', action='store_true', default=False,
                        help='Copy to content-addressed targets, not manifest')
    parser.add_argument('--sources', action='store_true', default=False,
                        help='Write source file per line, not manifest entry')
    parser.add_argument('--contents',
                        action='store_true', default=False,
                        help='Replace each source file name with its contents')
    parser.add_argument('--no-contents',
                        action='store_false', dest='contents',
                        help='Reset previous --contents')
    parser.add_argument(
        '--rewrite', action='append', default=[],
        metavar='PATTERN=ENTRY',
        help='Replace entries whose target matches PATTERN with ENTRY,'
        ' which can use {source} and {target} substitutions'),
    parser.add_argument('--reset-rewrite', dest='rewrite',
                        action='store_const', const=[],
                        help='Reset previous --rewrite')
    parser.add_argument('--unique',
                        action='store_true', default=False,
                        help='Elide duplicates even with different sources')
    parser.add_argument('--stamp',
                        metavar='FILE',
                        help='Touch FILE at the end.')
    args = common_parse_args(parser)
    if args.copy_contentaddr:
        if args.contents:
            parser.error('--copy-contentaddr is incompatible with --contents')
        args.unique = True
        args.sources = True
    return args


def main():
    args = parse_args()
    output_sets = [(dict() if args.unique else set()) for file in args.output]
    for entry in getattr(args, 'selected', []):
        assert entry.group is not None, entry
        if args.absolute:
            line = os.path.abspath(entry.source)
        else:
            line = entry.source
        if not args.sources:
            line = entry.target + args.separator + line
        if args.unique:
            output_sets[entry.group][entry.target] = line
        else:
            output_sets[entry.group].add(line)
    for output_filename, output_set in zip(args.output, output_sets):
        if args.copy_contentaddr:
            created_dirs = set()
            for target, source in output_set.iteritems():
                target_path = os.path.join(output_filename, target)
                if os.path.exists(target_path):
                    continue
                target_dir = os.path.dirname(target_path)
                if target_dir not in created_dirs:
                    if not os.path.exists(target_dir):
                        os.makedirs(target_dir)
                    created_dirs.add(target_dir)
                shutil.copyfile(source, target_path)
        else:
            with open(output_filename, 'w') as file:
                file.write(''.join(sorted(
                    line + '\n' for line in
                    (output_set.itervalues() if args.unique else output_set))))
    if args.stamp:
        with open(args.stamp, 'w') as file:
            os.utime(file.name, None)
    return 0


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