#!/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 fxbug.dev/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('--git-pubspecs', nargs='+',
                        help='A list of git pubspec locations formatted as DEP_NAME,GIT_URI,COMMIT_HASH,SUBDIR')
    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.
        dependencies = {
            package_name: 'any' for package_name in packages.keys()
        }
        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))

        overrides = {
            package_name: {
                'path': path,
            } for package_name, path in packages.iteritems()
        }
        # Start populating git-based dependencies.
        if args.git_pubspecs:
            debug_print('-----------------------------')
            debug_print('Mannualy-set git dependencies')
            debug_print('-----------------------------')
            for git_pubspec in args.git_pubspecs:
                dep_name, git_url, git_ref, git_path = git_pubspec.split(',')
                dependencies[dep_name] = 'any'
                overrides[dep_name] = {
                    'git': {
                        'url': git_url,
                        'ref': git_ref,
                        'path': git_path,
                    }
                }
            debug_print(yaml.safe_dump(dependencies, default_flow_style=False))

        with open(os.path.join(importer_dir, 'pubspec.yaml'), 'w') as pubspec:
            yaml.safe_dump({
                'name': 'importer',
                'dependencies': dependencies,
                'dependency_overrides': overrides,
            }, pubspec, default_flow_style=not args.debug)

        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())
