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

import argparse
import os
import paths
import shutil
import subprocess
import sys
import tempfile

sys.path += [os.path.join(paths.FUCHSIA_ROOT, 'third_party', 'pyyaml', 'lib')]
import yaml


LICENSE_FILES = ['LICENSE', 'LICENSE.txt']


IGNORED_EXTENSIONS = ['css', 'html', 'jpg', 'js', 'log', 'old', 'out',
                      'packages', 'png', 'snapshot', 'zip']

LOCAL_PACKAGES = {
  'analyzer': '//third_party/dart/pkg/analyzer',
  'build_integration': '//third_party/dart/pkg/build_integration',
  'flutter': '//third_party/dart-pkg/git/flutter/packages/flutter',
  'flutter_test': '//third_party/dart-pkg/git/flutter/packages/flutter_test',
  'front_end': '//third_party/dart/pkg/front_end',
  'func': '//third_party/dart/third_party/pkg/func',
  'intl': '//third_party/dart/third_party/pkg/intl',
  'kernel': '//third_party/dart/pkg/kernel',
  'testing': '//third_party/dart/pkg/testing',
  'linter': '//third_party/dart/third_party/pkg/linter',
  'typed_mock': '//third_party/dart/pkg/typed_mock',
}

FORBIDDEN_PACKAGES = ['mojo', 'mojo_services']

def parse_packages_file(dot_packages_path):
    """ parse the list of packages and paths in .packages file """
    packages = []
    with open(dot_packages_path) as dot_packages:
        # The packages specification says both '\r' and '\n' are valid line
        # delimiters, which matches Python's 'universal newline' concept.
        # Packages specification: https://github.com/dart-lang/dart_enhancement_proposals/blob/master/Accepted/0005%20-%20Package%20Specification/DEP-pkgspec.md
        contents = dot_packages.read()
        for line in unicode.splitlines(unicode(contents)):
            if line.startswith('#'):
                continue
            delim = line.find(':')
            if delim == -1:
                continue
            name = line[:delim]
            path = line[delim + 1:-1]
            packages.append((name, path))
    return packages


def parse_full_dependencies(yaml_path):
    """ parse the content of a pubspec.yaml """
    with open(yaml_path) as yaml_file:
        parsed = yaml.safe_load(yaml_file)
        if not parsed:
            raise Exception('Could not parse yaml file: %s' % yaml_file)
        package_name = parsed['name']
        get_deps = lambda dep_type: parsed[dep_type] if dep_type in parsed and parsed[dep_type] else {}
        deps = get_deps('dependencies')
        dev_deps = get_deps('dev_dependencies')
        dep_overrides = get_deps('dependency_overrides')
        return (package_name, deps, dev_deps, dep_overrides)


def parse_dependencies(yaml_path):
    """ parse the dependency map out of a pubspec.yaml """
    _, deps, _, _ = parse_full_dependencies(yaml_path)
    return deps


def write_build_file(build_gn_path, package_name, name_with_version, deps):
    """ writes BUILD.gn file for Dart package with dependencies """
    with open(build_gn_path, 'w') as build_gn:
        build_gn.write('''# This file is generated by importer.py for %s

import("//build/dart/dart_library.gni")

dart_library("%s") {
  package_name = "%s"

  # This parameter is left empty as we don't care about analysis or exporting
  # these sources outside of the tree.
  sources = []

  disable_analysis = true

  deps = [
''' % (name_with_version, package_name, package_name))
        for dep in deps:
            if dep in LOCAL_PACKAGES:
                build_gn.write('    "%s",\n' % LOCAL_PACKAGES[dep])
            else:
                build_gn.write('    "//third_party/dart-pkg/pub/%s",\n' % dep)
        build_gn.write('''  ]
}
''')


def read_package_versions(base):
    '''Scans the packages in a given directory.'''
    result = {}
    for (root, dirs, files) in os.walk(base):
        for dir in dirs:
            spec = os.path.join(root, dir, 'pubspec.yaml')
            if not os.path.exists(spec):
                continue
            with open(spec, 'r') as spec_file:
                data = yaml.safe_load(spec_file)
                result[data['name']] = data['version']
        break
    return result


def generate_package_diff(old_packages, new_packages, changelog):
    '''Writes a changelog file with package version changes.'''
    old = set(old_packages.iteritems())
    new = set(new_packages.iteritems())
    changed_keys = set([k for (k, _) in (old | new) - (old & new)])
    if not changed_keys:
        return
    max_key_width = max(map(lambda k: len(k), changed_keys))
    with open(changelog, 'w') as changelog_file:
        for key in sorted(changed_keys):
            old = old_packages.get(key, '<none>')
            new = new_packages.get(key, '<none>')
            changelog_file.write('%s %s --> %s\n' % (key.rjust(max_key_width),
                                                     old.rjust(10),
                                                     new.ljust(10)))


def main():
    parser = argparse.ArgumentParser('Import dart packages from pub')
    parser.add_argument('--pub', required=True,
                        help='Path to the pub executable')
    parser.add_argument('--pubspecs', nargs='+',
                        help='Paths to packages containing pubspec.yaml files')
    parser.add_argument('--projects', nargs='+',
                        help='Paths to projects containing dependency files')
    parser.add_argument('--output', required=True,
                        help='Path to the output directory')
    parser.add_argument('--changelog',
                        help='Path to the changelog file to write',
                        default=None)
    parser.add_argument('--debug',
                        help='Turns on debugging mode',
                        action='store_true')
    args = parser.parse_args()

    def debug_print(message):
        if args.debug:
            print(message)

    tempdir = tempfile.mkdtemp()
    debug_print('Working directory: ' + tempdir)
    try:
        importer_dir = os.path.join(tempdir, 'importer')
        os.mkdir(importer_dir)

        # Read the requested dependencies from the canonical packages.
        packages = {}
        additional_deps = {}
        debug_print('------------------------')
        debug_print('Development dependencies')
        debug_print('------------------------')
        for path in args.pubspecs:
            yaml_file = os.path.join(path, 'pubspec.yaml')
            package_name, _, dev_deps, _ = parse_full_dependencies(yaml_file)
            packages[package_name] = path
            additional_deps.update(dev_deps)
            debug_print('# From ' + yaml_file)
            for pair in sorted(dev_deps.items()):
                debug_print(' - %s: %s' % pair)

        # Generate a manifest containing all the dependencies we care about.
        manifest = {
            'name': 'importer',
        }
        dependencies = {}
        for package_name in packages.keys():
            dependencies[package_name] = 'any'
        for dep, version in additional_deps.iteritems():
            if dep in packages:
                continue
            dependencies[dep] = version
        debug_print('-------------------------')
        debug_print('Manually-set dependencies')
        debug_print('-------------------------')
        for project in args.projects:
            yaml_file = os.path.join(project, 'dart_dependencies.yaml')
            project_deps = parse_dependencies(yaml_file)
            debug_print('# From ' + yaml_file)
            for dep, version in sorted(project_deps.iteritems()):
                dependencies[dep] = version
                debug_print(' - %s: %s' % (dep, version))
        manifest['dependencies'] = dependencies
        overrides = {}
        for package_name, path in packages.iteritems():
            overrides[package_name] = {
                'path': path,
            }
        manifest['dependency_overrides'] = overrides
        with open(os.path.join(importer_dir, 'pubspec.yaml'), 'w') as pubspec:
            yaml.safe_dump(manifest, pubspec)

        old_packages = read_package_versions(args.output)

        # Use pub to load the dependencies into a local cache.
        pub_cache_dir = os.path.join(tempdir, 'pub_cache')
        os.mkdir(pub_cache_dir)
        env = os.environ
        env['PUB_CACHE'] = pub_cache_dir
        subprocess.check_call([args.pub, 'get'], cwd=importer_dir, env=env)

        # Walk the cache and copy the packages we are interested in.
        if os.path.exists(args.output):
            for (root, dirs, files) in os.walk(args.output):
                for dir in dirs:
                    if dir != '.git':
                        shutil.rmtree(os.path.join(root, dir))
                # Only process the root of the output tree.
                break

        pub_packages = parse_packages_file(os.path.join(importer_dir, '.packages'))
        for package in pub_packages:
            if package[0] in packages:
                # Skip canonical packages.
                continue
            if not package[1].startswith('file://'):
                continue
            source_dir = package[1][len('file://'):]
            if not os.path.exists(source_dir):
                continue
            if source_dir.find('pub.dartlang.org') == -1:
                print 'Package %s not from dartlang (%s), ignoring' % (package[0], source_dir)
                continue
            package_name = package[0]
            # Don't import packages that live canonically in the tree.
            if package_name in LOCAL_PACKAGES:
                continue
            if package_name in FORBIDDEN_PACKAGES:
                print 'Warning: dependency on forbidden package %s' % package_name
                continue
            # We expect the .packages file to point to a directory called 'lib'
            # inside the overall package, which will contain the LICENSE file
            # and other potentially useful directories like 'bin'.
            source_base_dir = os.path.dirname(os.path.abspath(source_dir))
            name_with_version = os.path.basename(source_base_dir)
            has_license = any(os.path.exists(os.path.join(source_base_dir, file_name))
                              for file_name in LICENSE_FILES)
            if not has_license:
                print 'Could not find license file for %s, skipping' % package_name
                continue
            pubspec_path = os.path.join(source_base_dir, 'pubspec.yaml')
            deps = []
            if os.path.exists(pubspec_path):
                deps = parse_dependencies(pubspec_path)
            dest_dir = os.path.join(args.output, package_name)
            shutil.copytree(source_base_dir, dest_dir,
                            ignore=shutil.ignore_patterns(
                                *('*.' + extension for extension in IGNORED_EXTENSIONS)))
            # We don't need the 'test' directory of packages we import as that
            # directory exists to test that package and some of our packages
            # have very heavy test directories, so nuke those.
            test_path = os.path.join(dest_dir, 'test')
            if os.path.exists(test_path):
                shutil.rmtree(test_path)
            write_build_file(os.path.join(dest_dir, 'BUILD.gn'), package_name,
                             name_with_version, deps)

        if args.changelog:
            new_packages = read_package_versions(args.output)
            generate_package_diff(old_packages, new_packages, args.changelog)

    finally:
        if not args.debug:
            shutil.rmtree(tempdir)

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