// Copyright (c) 2015, 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.

/// This tool checks that the output from dart2js meets a given specification,
/// given in a YAML file. The format of the YAML file is:
///
///     main:
///       include:
///         - some_package
///         - other_package
///
///     foo:
///       include:
///         - foo
///         - bar
///
///     baz:
///       include:
///         - baz
///         - quux
///       exclude:
///         - zardoz
///
/// The YAML file consists of a list of declarations, one for each deferred
/// part expected in the output. At least one of these parts must be named
/// "main"; this is the main part that contains the program entrypoint. Each
/// top-level part contains a list of package names that are expected to be
/// contained in that part, a list of package names that are expected to be in
/// another part, or both. For instance, in the example YAML above the part
/// named "baz" is expected to contain the packages "baz" and "quux" and not to
/// contain the package "zardoz".
///
/// The names for parts given in the specification YAML file (besides "main")
/// are the same as the name given to the deferred import in the dart file. For
/// instance, if you have `import 'package:foo/bar.dart' deferred as baz;` in
/// your dart file, then the corresponding name in the specification file is
/// 'baz'.
library dart2js_info.deferred_library_check;

import 'info.dart';

List<ManifestComplianceFailure> checkDeferredLibraryManifest(
    AllInfo info, Map manifest) {
  var includedPackages = <String, Set<String>>{};
  var excludedPackages = <String, Set<String>>{};
  for (var part in manifest.keys) {
    // ignore: avoid_dynamic_calls
    for (var package in manifest[part]['include'] ?? []) {
      (includedPackages[part] ??= {}).add(package);
    }
    // ignore: avoid_dynamic_calls
    for (var package in manifest[part]['exclude'] ?? []) {
      (excludedPackages[part] ??= {}).add(package);
    }
  }

  // There are 2 types of parts that are valid to mention in the specification
  // file. These are the main part and directly imported deferred parts. The
  // main part is always named 'main'; the directly imported deferred parts are
  // the outputUnits whose list of 'imports' contains a single import. If the
  // part is shared, it will have more than one import since it will include the
  // imports of all the top-level deferred parts that will load the shared part.
  List<String> validParts = [
    'main',
    ...info.outputUnits
        .where((unit) => unit.imports.length == 1)
        .map((unit) => unit.imports.single)
  ];
  List<String> mentionedParts = [
    ...includedPackages.keys,
    ...excludedPackages.keys
  ];
  var partNameFailures = <_InvalidPartName>[];
  for (var part in mentionedParts) {
    if (!validParts.contains(part)) {
      partNameFailures.add(_InvalidPartName(part, validParts));
    }
  }
  if (partNameFailures.isNotEmpty) {
    return partNameFailures;
  }

  var mentionedPackages = {
    for (var values in includedPackages.values) ...values,
    for (var values in excludedPackages.values) ...values
  };
  var actualIncludedPackages = <String, Set<String>>{};

  var failures = <ManifestComplianceFailure>[];

  void checkInfo(BasicInfo info) {
    if (info.size == 0) return;
    var lib = _getLibraryOf(info);
    if (lib != null && _isPackageUri(lib.uri)) {
      var packageName = _getPackageName(lib.uri);
      if (!mentionedPackages.contains(packageName)) return;
      var containingParts = <String>[];
      if (info.outputUnit!.name == 'main') {
        containingParts.add('main');
      } else {
        containingParts.addAll(info.outputUnit!.imports);
      }
      for (var part in containingParts) {
        (actualIncludedPackages[part] ??= {}).add(packageName);
        if (excludedPackages[part]!.contains(packageName)) {
          failures.add(_PartContainedExcludedPackage(part, packageName, info));
        }
      }
    }
  }

  info.functions.forEach(checkInfo);
  info.fields.forEach(checkInfo);

  includedPackages.forEach((part, packages) {
    for (var package in packages) {
      if (!actualIncludedPackages.containsKey(part) ||
          !actualIncludedPackages[part]!.contains(package)) {
        failures.add(_PartDidNotContainPackage(part, package));
      }
    }
  });
  return failures;
}

LibraryInfo? _getLibraryOf(Info info) {
  Info? current = info;
  while (current is! LibraryInfo) {
    if (current == null) {
      return null;
    }
    current = current.parent;
  }
  return current;
}

bool _isPackageUri(Uri uri) => uri.isScheme('package');

String _getPackageName(Uri uri) {
  assert(_isPackageUri(uri));
  return uri.pathSegments.first;
}

class ManifestComplianceFailure {
  const ManifestComplianceFailure();
}

class _InvalidPartName extends ManifestComplianceFailure {
  final String part;
  final List<String> validPartNames;
  const _InvalidPartName(this.part, this.validPartNames);

  @override
  String toString() {
    return 'Manifest file declares invalid part "$part". '
        'Valid part names are: $validPartNames';
  }
}

class _PartContainedExcludedPackage extends ManifestComplianceFailure {
  final String part;
  final String package;
  final BasicInfo info;
  const _PartContainedExcludedPackage(this.part, this.package, this.info);

  @override
  String toString() {
    return 'Part "$part" was specified to exclude package "$package" but it '
        'actually contains ${kindToString(info.kind)} "${info.name}" which '
        'is from package "$package"';
  }
}

class _PartDidNotContainPackage extends ManifestComplianceFailure {
  final String part;
  final String package;
  const _PartDidNotContainPackage(this.part, this.package);

  @override
  String toString() {
    return 'Part "$part" was specified to include package "$package" but it '
        'does not contain any elements from that package.';
  }
}
