#!/usr/bin/env dart

/// Generates the repo's ".dart_tool/package_config.json" file.
import 'dart:convert';
import 'dart:io';

import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';

final repoRoot = p.dirname(p.dirname(p.fromUri(Platform.script)));
final configFilePath = p.join(repoRoot, '.dart_tool/package_config.json');

void main(List<String> args) {
  var packageDirs = [
    ...listSubdirectories('pkg'),
    ...listSubdirectories('third_party/pkg'),
    ...listSubdirectories('third_party/pkg_tested'),
    ...listSubdirectories('third_party/pkg/test/pkgs'),
    packageDirectory('runtime/observatory'),
    packageDirectory(
        'runtime/observatory/tests/service/observatory_test_package'),
    packageDirectory('runtime/observatory_2'),
    packageDirectory(
        'runtime/observatory_2/tests/service_2/observatory_test_package_2'),
    packageDirectory('sdk/lib/_internal/sdk_library_metadata'),
    packageDirectory('sdk/lib/_internal/js_runtime'),
    packageDirectory('third_party/pkg/protobuf/protobuf'),
  ];

  var cfePackageDirs = [
    packageDirectory('pkg/front_end/testcases/'),
  ];

  var feAnalyzerSharedPackageDirs = [
    packageDirectory(
        'pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/'),
    packageDirectory(
        'pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/'),
    packageDirectory(
        'pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/'),
    packageDirectory('pkg/_fe_analyzer_shared/test/flow_analysis/nullability/'),
    packageDirectory(
        'pkg/_fe_analyzer_shared/test/flow_analysis/reachability/'),
    packageDirectory(
        'pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/'),
    packageDirectory('pkg/_fe_analyzer_shared/test/inheritance/'),
  ];

  var packages = [
    ...makePackageConfigs(packageDirs),
    ...makeCfePackageConfigs(cfePackageDirs),
    ...makeFeAnalyzerSharedPackageConfigs(feAnalyzerSharedPackageDirs)
  ];
  packages.sort((a, b) => a["name"].compareTo(b["name"]));

  var year = DateTime.now().year;
  var config = <String, dynamic>{
    'copyright': [
      'Copyright (c) $year, the Dart project authors. Please see the AUTHORS ',
      'file for details. All rights reserved. Use of this source code is ',
      'governed by a BSD-style license that can be found in the LICENSE file.'
    ],
    'comment': [
      'Package configuration for all packages in /pkg, and checked out by DEPS',
      'into /third_party/pkg and /third_party/pkg_tested.',
      'If you add a package to DEPS or /pkg or change a package\'s SDK',
      'constraint, update this by running tools/generate_package_config.dart.'
    ],
    'configVersion': 2,
    'generated': DateTime.now().toIso8601String(),
    'generator': 'tools/generate_package_config.dart',
    'packages': packages,
  };

  // TODO(rnystrom): Consider using package_config_v2 to generate this instead.
  var json = JsonEncoder.withIndent('  ').convert(config);
  File(p.join(repoRoot, '.dart_tool', 'package_config.json'))
      .writeAsStringSync(json);
  print('Generated .dart_tool/package_config.dart containing '
      '${packages.length} packages.');
}

/// Generates package configurations for each package in [packageDirs].
Iterable<Map<String, String>> makePackageConfigs(
    List<String> packageDirs) sync* {
  for (var packageDir in packageDirs) {
    var version = pubspecLanguageVersion(packageDir);
    var hasLibDirectory = Directory(p.join(packageDir, 'lib')).existsSync();

    yield {
      'name': p.basename(packageDir),
      'rootUri': p
          .toUri(p.relative(packageDir, from: p.dirname(configFilePath)))
          .toString(),
      if (hasLibDirectory) 'packageUri': 'lib/',
      if (version != null)
        'languageVersion': '${version.major}.${version.minor}'
    };
  }
}

/// Generates package configurations for the special pseudo-packages used by
/// the CFE unit tests (`pkg/front_end/test/unit_test_suites.dart`).
Iterable<Map<String, String>> makeCfePackageConfigs(
    List<String> packageDirs) sync* {
  for (var packageDir in packageDirs) {
    yield {
      'name': 'front_end_${p.basename(packageDir)}',
      'rootUri': p
          .toUri(p.relative(packageDir, from: p.dirname(configFilePath)))
          .toString(),
      'packageUri': '.nonexisting/',
    };
  }
}

/// Generates package configurations for the special pseudo-packages used by
/// the _fe_analyzer_shared id tests.
Iterable<Map<String, String>> makeFeAnalyzerSharedPackageConfigs(
    List<String> packageDirs) sync* {
  for (var packageDir in packageDirs) {
    yield {
      'name': '_fe_analyzer_shared_${p.basename(packageDir)}',
      'rootUri': p
          .toUri(p.relative(packageDir, from: p.dirname(configFilePath)))
          .toString(),
      'packageUri': '.nonexisting/',
    };
  }
}

/// Generates a path to [relativePath] within the repo.
String packageDirectory(String relativePath) => p.join(repoRoot, relativePath);

/// Finds the paths of the immediate subdirectories of [packagesDir] that
/// contain pubspecs.
Iterable<String> listSubdirectories(String packagesDir) sync* {
  for (var entry in Directory(p.join(repoRoot, packagesDir)).listSync()) {
    if (entry is! Directory) continue;
    if (!File(p.join(entry.path, 'pubspec.yaml')).existsSync()) continue;
    yield entry.path;
  }
}

/// Infers the language version from the SDK constraint in the pubspec for
/// [packageDir].
///
/// Returns `null` if there is no pubspec or no SDK constraint.
Version pubspecLanguageVersion(String packageDir) {
  var pubspecFile = File(p.join(packageDir, 'pubspec.yaml'));

  if (!pubspecFile.existsSync()) return null;

  var pubspec =
      loadYaml(pubspecFile.readAsStringSync()) as Map<dynamic, dynamic>;
  if (!pubspec.containsKey('environment')) return null;

  var environment = pubspec['environment'] as Map<dynamic, dynamic>;
  if (!environment.containsKey('sdk')) return null;

  var sdkConstraint = VersionConstraint.parse(environment['sdk'] as String);
  if (sdkConstraint is VersionRange) return sdkConstraint.min;

  return null;
}
