#!/usr/bin/env python2.7
# 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 json
import os
import paths
import re
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', 'js', 'log', 'old', 'out',
                      'packages', 'snapshot', 'zip']

LOCAL_PACKAGES = {
  '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',
  'flutter_web_plugins': '//third_party/dart-pkg/git/flutter/packages/flutter_web_plugins',
  'func': '//third_party/dart/third_party/pkg/func',
  'sky_engine': '//prebuilt/third_party/sky_engine',
  'testing': '//third_party/dart/pkg/testing',
  'typed_mock': '//third_party/dart/pkg/typed_mock',
}

FORBIDDEN_PACKAGES = ['mojo', 'mojo_services']

# This is to account for https://github.com/flutter/devtools/issues/1148
PACKAGES_WITH_NO_LIB = ['devtools']


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 get_deps(package_name, parsed_yaml, dep_type):
    if dep_type in parsed_yaml and parsed_yaml[dep_type]:
        deps = parsed_yaml[dep_type]
        # This is to avoid circular dependencies. See fxb/40784.
        if package_name == 'built_value' and 'built_value_generator' in deps:
            del deps['built_value_generator']
        return deps
    else:
        return {}


def safe_parse_yaml(yaml_path):
    """ parses a pubspec file that may be malformed """
    # Some yaml files can be malformed and have an extra tab at the end
    # of a line. This causes the parser to fail so we strip all tabs off
    # the end of the lines.
    with open(yaml_path) as yaml_file:
        yaml_data = []
        for line in yaml_file.readlines():
            yaml_data.append(line.rstrip('\t\n'))
        yaml_doc = "\n".join(yaml_data)

        parsed = yaml.safe_load(yaml_doc)
        if not parsed:
            raise Exception('Could not parse yaml file: %s' % yaml_file)

    return parsed


def parse_min_sdk_version_and_full_dependencies(yaml_path):
    """ parse the content of a pubspec.yaml """
    parsed = safe_parse_yaml(yaml_path)

    package_name = parsed['name']
    # If a format like sdk: '>=a.b' or sdk: 'a.b' is found, we'll use a.b.
    # If sdk is not specified (or 'any'), 2.8 is used.
    # In all other cases 2.0 is used.
    env_sdk = parsed.get('environment', {}).get('sdk', 'any')
    match = re.search(r"^(>=)?((0|[1-9]\d*)\.(0|[1-9]\d*))", env_sdk)
    if match:
        min_sdk_version = match.group(2)
    elif env_sdk == 'any':
        min_sdk_version = '2.8'
    else:
        min_sdk_version = '2.0'
    deps = get_deps(package_name, parsed, 'dependencies')
    dev_deps = get_deps(package_name, parsed, 'dev_dependencies')
    dep_overrides = get_deps(package_name, parsed, 'dependency_overrides')
    return (package_name, min_sdk_version, deps, dev_deps, dep_overrides)


def parse_min_sdk_and_dependencies(yaml_path):
    """ parse the min sdk version and dependency map out of a pubspec.yaml """
    _, min_sdk_version, deps, _, _ = parse_min_sdk_version_and_full_dependencies(yaml_path)
    return min_sdk_version, deps


def write_build_file(build_gn_path, package_name, name_with_version, language_version, deps, dart_sources):
    """ 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"

  language_version = "%s"

  disable_analysis = true

  deps = [
''' % (name_with_version, package_name, package_name, language_version))
        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('''  ]

  sources = [
''')
        for source in sorted(dart_sources):
            build_gn.write('    "%s",\n' % source)
        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
            data = safe_parse_yaml(spec)
            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 valid_package_path(package_name, source_dir):
    if package_name in PACKAGES_WITH_NO_LIB:
        parent_dir = os.path.normpath(os.path.join(source_dir, os.pardir))
        return os.path.exists(parent_dir)
    else:
        return os.path.exists(source_dir)


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_min_sdk_version_and_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_min_sdk_and_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
        pub_get = [args.pub, 'get']
        if args.debug:
            pub_get.append('-v')
        subprocess.check_call(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'))
        package_config = {
          'configVersion': 2,
          'packages': [],
          'generator': os.path.basename(__file__)
        }
        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://'):]
            package_name = package[0]
            if not valid_package_path(package_name, source_dir):
                continue
            if source_dir.find('pub.dartlang.org') == -1:
                print 'Package %s not from dartlang (%s), ignoring' % (package[0], source_dir)
                continue
            # 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 = []
            min_sdk_version = '2.8'
            if os.path.exists(pubspec_path):
                min_sdk_version, deps = parse_min_sdk_and_dependencies(pubspec_path)
            dest_dir = os.path.join(args.output, package_name)
            dart_sources = []
            # Add all dart files in source_dir subdirectory into dart_sources
            for (path, dirs, files) in os.walk(source_dir):
                for f in files:
                    if f.endswith('.dart'):
                        dart_sources.append(
                            os.path.relpath(os.path.join(path, f), source_dir))
            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, min_sdk_version, deps, dart_sources)
            # All pub packages are required to have a lib/ dir, so it's safe to
            # hard-code this value.
            package_config['packages'].append({
              'name': package_name,
              'rootUri': './%s/' % package_name,
              'packageUri': 'lib/',
              'languageVersion': min_sdk_version
            })
        # args.output == '//third_party/dart-pkg/pub/', so we'll try to
        # serialize package_config to JSON by using json.dumps and write to
        # //third_party/dart-pkg/pub/package_config.json.
        with open(os.path.join(args.output, 'package_config.json'), 'w') as package_config_json:
          package_config_json.write(json.dumps(package_config, sort_keys=True, indent=2))
        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())
