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

// @dart=2.10

import 'dart:convert';

import 'package:collection/collection.dart' hide mapMap;
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
import 'package:source_span/source_span.dart';
import 'package:yaml/yaml.dart';

import 'io.dart';
import 'language_version.dart';
import 'package_config.dart';
import 'package_name.dart';
import 'packages_file.dart' as packages_file;
import 'sdk.dart' show sdk;
import 'source_registry.dart';
import 'system_cache.dart';
import 'utils.dart';

/// A parsed and validated `pubspec.lock` file.
class LockFile {
  /// The packages this lockfile pins.
  final Map<String, PackageId> packages;

  /// The intersections of all SDK constraints for all locked packages, indexed
  /// by SDK identifier.
  Map<String, VersionConstraint> sdkConstraints;

  /// Dependency names that appeared in the root package's `dependencies`
  /// section.
  final Set<String> _mainDependencies;

  /// Dependency names that appeared in the root package's `dev_dependencies`
  /// section.
  final Set<String> _devDependencies;

  /// Dependency names that appeared in the root package's
  /// `dependency_overrides` section.
  final Set<String> _overriddenDependencies;

  /// Creates a new lockfile containing [ids].
  ///
  /// If passed, [mainDependencies], [devDependencies], and
  /// [overriddenDependencies] indicate which dependencies should be marked as
  /// being listed in the main package's `dependencies`, `dev_dependencies`, and
  /// `dependency_overrides` sections, respectively. These are consumed by the
  /// analysis server to provide better auto-completion.
  LockFile(Iterable<PackageId> ids,
      {Map<String, VersionConstraint> sdkConstraints,
      Set<String> mainDependencies,
      Set<String> devDependencies,
      Set<String> overriddenDependencies})
      : this._(
            Map.fromIterable(ids.where((id) => !id.isRoot),
                key: (id) => id.name),
            sdkConstraints ?? {'dart': VersionConstraint.any},
            mainDependencies ?? const UnmodifiableSetView.empty(),
            devDependencies ?? const UnmodifiableSetView.empty(),
            overriddenDependencies ?? const UnmodifiableSetView.empty());

  LockFile._(
      Map<String, PackageId> packages,
      this.sdkConstraints,
      this._mainDependencies,
      this._devDependencies,
      this._overriddenDependencies)
      : packages = UnmodifiableMapView(packages);

  LockFile.empty()
      : packages = const {},
        sdkConstraints = {'dart': VersionConstraint.any},
        _mainDependencies = const UnmodifiableSetView.empty(),
        _devDependencies = const UnmodifiableSetView.empty(),
        _overriddenDependencies = const UnmodifiableSetView.empty();

  /// Loads a lockfile from [filePath].
  factory LockFile.load(String filePath, SourceRegistry sources) {
    return LockFile._parse(filePath, readTextFile(filePath), sources);
  }

  /// Parses a lockfile whose text is [contents].
  factory LockFile.parse(String contents, SourceRegistry sources) {
    return LockFile._parse(null, contents, sources);
  }

  /// Parses the lockfile whose text is [contents].
  ///
  /// [filePath] is the system-native path to the lockfile on disc. It may be
  /// `null`.
  static LockFile _parse(
      String filePath, String contents, SourceRegistry sources) {
    if (contents.trim() == '') return LockFile.empty();

    Uri sourceUrl;
    if (filePath != null) sourceUrl = p.toUri(filePath);
    var parsed = loadYamlNode(contents, sourceUrl: sourceUrl);

    _validate(parsed is Map, 'The lockfile must be a YAML mapping.', parsed);
    var parsedMap = parsed as YamlMap;

    var sdkConstraints = <String, VersionConstraint>{};
    var sdkNode = parsedMap.nodes['sdk'];
    if (sdkNode != null) {
      // Lockfiles produced by pub versions from 1.14.0 through 1.18.0 included
      // a top-level "sdk" field which encoded the unified constraint on the
      // Dart SDK. They had no way of specifying constraints on other SDKs.
      sdkConstraints['dart'] = _parseVersionConstraint(sdkNode);
    } else if (parsedMap.containsKey('sdks')) {
      var sdksField = parsedMap['sdks'];
      _validate(sdksField is Map, 'The "sdks" field must be a mapping.',
          parsedMap.nodes['sdks']);

      sdksField.nodes.forEach((name, constraint) {
        _validate(name.value is String, 'SDK names must be strings.', name);
        sdkConstraints[name.value as String] =
            _parseVersionConstraint(constraint);
      });
    }

    var packages = <String, PackageId>{};
    var packageEntries = parsedMap['packages'];
    if (packageEntries != null) {
      _validate(packageEntries is Map, 'The "packages" field must be a map.',
          parsedMap.nodes['packages']);

      packageEntries.forEach((name, spec) {
        // Parse the version.
        _validate(spec.containsKey('version'),
            'Package $name is missing a version.', spec);
        var version = Version.parse(spec['version']);

        // Parse the source.
        _validate(spec.containsKey('source'),
            'Package $name is missing a source.', spec);
        var sourceName = spec['source'];

        _validate(spec.containsKey('description'),
            'Package $name is missing a description.', spec);
        var description = spec['description'];

        // Let the source parse the description.
        var source = sources[sourceName];
        PackageId id;
        try {
          id = source.parseId(name, version, description,
              containingPath: filePath);
        } on FormatException catch (ex) {
          throw SourceSpanFormatException(
              ex.message, spec.nodes['description'].span);
        }

        // Validate the name.
        _validate(name == id.name,
            "Package name $name doesn't match ${id.name}.", spec);

        packages[name] = id;
      });
    }

    return LockFile._(
        packages,
        sdkConstraints,
        const UnmodifiableSetView.empty(),
        const UnmodifiableSetView.empty(),
        const UnmodifiableSetView.empty());
  }

  /// Asserts that [node] is a version constraint, and parses it.
  static VersionConstraint _parseVersionConstraint(YamlNode node) {
    if (node == null) return null;

    _validate(node.value is String,
        'Invalid version constraint: must be a string.', node);

    return _wrapFormatException('version constraint', node.span,
        () => VersionConstraint.parse(node.value));
  }

  /// Runs [fn] and wraps any [FormatException] it throws in a
  /// [SourceSpanFormatException].
  ///
  /// [description] should be a noun phrase that describes whatever's being
  /// parsed or processed by [fn]. [span] should be the location of whatever's
  /// being processed within the pubspec.
  static T _wrapFormatException<T>(
      String description, SourceSpan span, T Function() fn) {
    try {
      return fn();
    } on FormatException catch (e) {
      throw SourceSpanFormatException(
          'Invalid $description: ${e.message}', span);
    }
  }

  /// If [condition] is `false` throws a format error with [message] for [node].
  static void _validate(bool condition, String message, YamlNode node) {
    if (condition) return;
    throw SourceSpanFormatException(message, node.span);
  }

  /// Returns a copy of this LockFile with a package named [name] removed.
  ///
  /// Returns an identical [LockFile] if there's no package named [name].
  LockFile removePackage(String name) {
    if (!this.packages.containsKey(name)) return this;

    var packages = Map<String, PackageId>.from(this.packages);
    packages.remove(name);
    return LockFile._(packages, sdkConstraints, _mainDependencies,
        _devDependencies, _overriddenDependencies);
  }

  /// Returns the contents of the `.packages` file generated from this lockfile.
  ///
  /// If [entrypoint] is passed, a relative entry is added for its "lib/"
  /// directory.
  String packagesFile(
    SystemCache cache, {
    String entrypoint,
    @required String relativeFrom,
  }) {
    var header = '''
This file is deprecated. Tools should instead consume 
`.dart_tool/package_config.json`.

For more info see: https://dart.dev/go/dot-packages-deprecation

Generated by pub on ${DateTime.now()}.''';

    var map =
        Map<String, Uri>.fromIterable(ordered(packages.keys), value: (name) {
      var id = packages[name];
      var source = cache.source(id.source);
      return p.toUri(
          p.join(source.getDirectory(id, relativeFrom: relativeFrom), 'lib'));
    });

    if (entrypoint != null) map[entrypoint] = Uri.parse('lib/');

    var text = StringBuffer();
    packages_file.write(text, map, comment: header);
    return text.toString();
  }

  /// Returns the contents of the `.dart_tool/package_config` file generated
  /// from this lockfile.
  ///
  /// This file will replace the `.packages` file.
  ///
  /// If [entrypoint] is passed, an accompanying [entrypointSdkConstraint]
  /// should be given, these identify the current package in which this file is
  /// written. Passing `null` as [entrypointSdkConstraint] is correct if the
  /// current package has no SDK constraint.
  Future<String> packageConfigFile(
    SystemCache cache, {
    String entrypoint,
    VersionConstraint entrypointSdkConstraint,
    @required String relativeFrom,
  }) async {
    final entries = <PackageConfigEntry>[];
    for (final name in ordered(packages.keys)) {
      final id = packages[name];
      final source = cache.source(id.source);
      final rootPath = source.getDirectory(id, relativeFrom: relativeFrom);
      Uri rootUri;
      if (p.isRelative(rootPath)) {
        // Relative paths are relative to the root project, we want them
        // relative to the `.dart_tool/package_config.json` file.
        rootUri = p.toUri(p.join('..', rootPath));
      } else {
        rootUri = p.toUri(rootPath);
      }
      final pubspec = await source.describe(id);
      final sdkConstraint = pubspec.sdkConstraints[sdk.identifier];
      entries.add(PackageConfigEntry(
        name: name,
        rootUri: rootUri,
        packageUri: p.toUri('lib/'),
        languageVersion: LanguageVersion.fromSdkConstraint(sdkConstraint),
      ));
    }

    if (entrypoint != null) {
      entries.add(PackageConfigEntry(
        name: entrypoint,
        rootUri: p.toUri('../'),
        packageUri: p.toUri('lib/'),
        languageVersion: LanguageVersion.fromSdkConstraint(
          entrypointSdkConstraint,
        ),
      ));
    }

    final packageConfig = PackageConfig(
      configVersion: 2,
      packages: entries,
      generated: DateTime.now(),
      generator: 'pub',
      generatorVersion: sdk.version,
    );

    return JsonEncoder.withIndent('  ').convert(packageConfig.toJson()) + '\n';
  }

  /// Returns the serialized YAML text of the lock file.
  ///
  /// [packageDir] is the containing directory of the root package, used to
  /// properly serialize package descriptions.
  String serialize(String packageDir) {
    // Convert the dependencies to a simple object.
    var packageMap = {};
    packages.forEach((name, package) {
      var description =
          package.source.serializeDescription(packageDir, package.description);

      packageMap[name] = {
        'version': package.version.toString(),
        'source': package.source.name,
        'description': description,
        'dependency': _dependencyType(package.name)
      };
    });

    var data = {
      'sdks': mapMap(sdkConstraints,
          value: (_, constraint) => constraint.toString()),
      'packages': packageMap
    };
    return '''
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
${yamlToString(data)}
''';
  }

  /// Returns the dependency classification for [package].
  String _dependencyType(String package) {
    if (_mainDependencies.contains(package)) return 'direct main';
    if (_devDependencies.contains(package)) return 'direct dev';

    // If a package appears in `dependency_overrides` and another dependency
    // section, the main section it appears in takes precedence.
    if (_overriddenDependencies.contains(package)) {
      return 'direct overridden';
    }
    return 'transitive';
  }

  /// `true` if [other] has the same packages as `this` in the same versions
  /// from the same sources.
  bool samePackageIds(LockFile other) {
    if (packages.length != other.packages.length) {
      return false;
    }
    for (final id in packages.values) {
      final otherId = other.packages[id.name];
      if (id != otherId) return false;
    }
    return true;
  }
}
