// 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.

/// Attempts to resolve a set of version constraints for a package dependency
/// graph and select an appropriate set of best specific versions for all
/// dependent packages. It works iteratively and tries to reach a stable
/// solution where the constraints of all dependencies are met. If it fails to
/// reach a solution after a certain number of iterations, it assumes the
/// dependency graph is unstable and reports and error.
///
/// There are two fundamental operations in the process of iterating over the
/// graph:
///
/// 1.  Changing the selected concrete version of some package. (This includes
///     adding and removing a package too, which is considering changing the
///     version to or from "none".) In other words, a node has changed.
/// 2.  Changing the version constraint that one package places on another. In
///     other words, and edge has changed.
///
/// Both of these events have a corresponding (potentional) async operation and
/// roughly cycle back and forth between each other. When we change the version
/// of package changes, we asynchronously load the pubspec for the new version.
/// When that's done, we compare the dependencies of the new version versus the
/// old one. For everything that differs, we change those constraints between
/// this package and that dependency.
///
/// When a constraint on a package changes, we re-calculate the overall
/// constraint on that package. I.e. with a shared dependency, we intersect all
/// of the constraints that its depending packages place on it. If that overall
/// constraint changes (say from "<3.0.0" to "<2.5.0"), then the currently
/// picked version for that package may fall outside of the new constraint. If
/// that happens, we find the new best version that meets the updated constraint
/// and then the change the package to use that version. That cycles back up to
/// the beginning again.
library version_solver;

import 'dart:async';
import 'dart:json' as json;
import 'dart:math';
import 'lock_file.dart';
import 'log.dart' as log;
import 'package.dart';
import 'pubspec.dart';
import 'root_source.dart';
import 'source.dart';
import 'source_registry.dart';
import 'utils.dart';
import 'version.dart';

/// Attempts to select the best concrete versions for all of the transitive
/// dependencies of [root] taking into account all of the [VersionConstraint]s
/// that those dependencies place on each other and the requirements imposed by
/// [lockFile]. If successful, completes to a [Map] that maps package names to
/// the selected version for that package. If it fails, the future will complete
/// with a [NoVersionException], [DisjointConstraintException], or
/// [CouldNotSolveException].
Future<List<PackageId>> resolveVersions(SourceRegistry sources, Package root,
    LockFile lockFile) {
  log.message('Resolving dependencies...');
  return new VersionSolver(sources, root, lockFile).solve();
}

class VersionSolver {
  final SourceRegistry _sources;
  final Package _root;
  final LockFile lockFile;
  final PubspecCache _pubspecs;
  final Map<String, Dependency> _packages;
  final Queue<WorkItem> _work;
  int _numIterations = 0;

  VersionSolver(SourceRegistry sources, this._root, this.lockFile)
      : _sources = sources,
        _pubspecs = new PubspecCache(sources),
        _packages = <String, Dependency>{},
        _work = new Queue<WorkItem>();

  /// Tell the version solver to use the most recent version of [package] that
  /// exists in whatever source it's installed from. If that version violates
  /// constraints imposed by other dependencies, an error will be raised when
  /// solving the versions, even if an earlier compatible version exists.
  void useLatestVersion(String package) {
    // TODO(nweiz): How do we want to detect and handle unknown dependencies
    // here?
    getDependency(package).useLatestVersion = true;
    lockFile.packages.remove(package);
  }

  Future<List<PackageId>> solve() {
    // Kick off the work by adding the root package at its concrete version to
    // the dependency graph.
    var ref = new PackageRef(
        _root.name, new RootSource(_root), _root.version, _root.name);
    enqueue(new AddConstraint('(entrypoint)', ref));
    _pubspecs.cache(ref.atVersion(_root.version), _root.pubspec);

    Future processNextWorkItem(_) {
      while (true) {
        // Stop if we are done.
        if (_work.isEmpty) return new Future.immediate(buildResults());

        // If we appear to be stuck in a loop, then we probably have an unstable
        // graph, bail. We guess this based on a rough heuristic that it should
        // only take a certain number of steps to solve a graph with a given
        // number of connections.
        // TODO(rnystrom): These numbers here are magic and arbitrary. Tune
        // when we have a better picture of real-world package topologies.
        _numIterations++;
        if (_numIterations > max(50, _packages.length * 5)) {
          throw new CouldNotSolveException();
        }

        // Run the first work item.
        var future = _work.removeFirst().process(this);

        // If we have an async operation to perform, chain the loop to resume
        // when it's done. Otherwise, just loop synchronously.
        if (future != null) {
          return future.then(processNextWorkItem);
        }
      }
    }

    return processNextWorkItem(null);
  }

  void enqueue(WorkItem work) {
    _work.add(work);
  }

  Dependency getDependency(String package) {
    // There can be unused dependencies in the graph, so just create an empty
    // one if needed.
    _packages.putIfAbsent(package, () => new Dependency(package));
    return _packages[package];
  }

  /// Sets the best selected version of [package] to [version].
  void setVersion(String package, Version version) {
    _packages[package].version = version;
  }

  /// Returns the most recent version of [dependency] that satisfies all of its
  /// version constraints.
  Future<Version> getBestVersion(Dependency dependency) {
    return dependency.getVersions().then((versions) {
      var best = null;
      for (var version in versions) {
        if (dependency.useLatestVersion ||
            dependency.constraint.allows(version)) {
          if (best == null || version > best) best = version;
        }
      }

      // TODO(rnystrom): Better exception.
      if (best == null) {
        if (tryUnlockDepender(dependency)) return null;
        throw new NoVersionException(dependency.name, dependency.constraint,
            dependency._refs);
      } else if (!dependency.constraint.allows(best)) {
        if (tryUnlockDepender(dependency)) return null;
        throw new CouldNotUpdateException(
            dependency.name, dependency.constraint, best);
      }

      return best;
    });
  }

  /// Looks for a package that depends (transitively) on [dependency] and has
  /// its version locked in the lockfile. If one is found, enqueues an
  /// [UnlockPackage] work item for it and returns true. Otherwise, returns
  /// false.
  ///
  /// This does a breadth-first search; immediate dependers will be unlocked
  /// first, followed by transitive dependers.
  bool tryUnlockDepender(Dependency dependency, [Set<String> seen]) {
    if (seen == null) seen = new Set();
    // Avoid an infinite loop if there are circular dependencies.
    if (seen.contains(dependency.name)) return false;
    seen.add(dependency.name);

    for (var dependerName in dependency.dependers) {
      var depender = getDependency(dependerName);
      var locked = lockFile.packages[dependerName];
      if (locked != null && depender.version == locked.version) {
        enqueue(new UnlockPackage(depender));
        return true;
      }
    }

    return dependency.dependers.mappedBy(getDependency).any((subdependency) =>
        tryUnlockDepender(subdependency, seen));
  }

  List<PackageId> buildResults() {
    return _packages.values.where((dep) => dep.isDependedOn).mappedBy((dep) {
      var description = dep.description;

      // If the lockfile contains a fully-resolved description for the package,
      // use that. This allows e.g. Git to ensure that the same commit is used.
      var lockedPackage = lockFile.packages[dep.name];
      if (lockedPackage != null && lockedPackage.version == dep.version &&
          lockedPackage.source.name == dep.source.name &&
          dep.source.descriptionsEqual(
              description, lockedPackage.description)) {
        description = lockedPackage.description;
      }

      return new PackageId(dep.name, dep.source, dep.version, description);
    })
    .toList();
  }
}

/// The constraint solver works by iteratively processing a queue of work items.
/// Each item is a single atomic change to the dependency graph. Handling them
/// in a queue lets us handle asynchrony (resolving versions requires
/// information from servers) as well as avoid deeply nested recursion.
abstract class WorkItem {
  /// Processes this work item. Returns a future that completes when the work is
  /// done. If `null` is returned, that means the work has completed
  /// synchronously and the next item can be started immediately.
  Future process(VersionSolver solver);
}

/// The best selected version for a package has changed to [version]. If the
/// previous version of the package is `null`, that means the package is being
/// added to the graph. If [version] is `null`, it is being removed.
class ChangeVersion implements WorkItem {
  /// The name of the package whose version is being changed.
  final String package;

  /// The source of the package whose version is changing.
  final Source source;

  /// The description identifying the package whose version is changing.
  final description;

  /// The new selected version.
  final Version version;

  ChangeVersion(this.package, this.source, this.description, this.version) {
    if (source == null) throw "null source";
  }

  Future process(VersionSolver solver) {
    log.fine("Changing $package to version $version.");

    var dependency = solver.getDependency(package);
    var oldVersion = dependency.version;
    solver.setVersion(package, version);

    // The dependencies between the old and new version may be different. Walk
    // them both and update any constraints that differ between the two.
    return Future.wait([
        getDependencyRefs(solver, oldVersion),
        getDependencyRefs(solver, version)]).then((list) {
      var oldDependencyRefs = list[0];
      var newDependencyRefs = list[1];

      for (var oldRef in oldDependencyRefs.values) {
        if (newDependencyRefs.containsKey(oldRef.name)) {
          // The dependency is in both versions of this package, but its
          // constraint may have changed.
          var newRef = newDependencyRefs.remove(oldRef.name);
          solver.enqueue(new AddConstraint(package, newRef));
        } else {
          // The dependency is not in the new version of the package, so just
          // remove its constraint.
          solver.enqueue(new RemoveConstraint(package, oldRef.name));
        }
      }

      // Everything that's left is a depdendency that's only in the new
      // version of the package.
      for (var newRef in newDependencyRefs.values) {
        solver.enqueue(new AddConstraint(package, newRef));
      }
    });
  }

  /// Get the dependencies at [version] of the package being changed.
  Future<Map<String, PackageRef>> getDependencyRefs(VersionSolver solver,
      Version version) {
    // If there is no version, it means no package, so no dependencies.
    if (version == null) {
      return
          new Future<Map<String, PackageRef>>.immediate(<String, PackageRef>{});
    }

    var id = new PackageId(package, source, version, description);
    return solver._pubspecs.load(id).then((pubspec) {
      var dependencies = <String, PackageRef>{};
      for (var dependency in pubspec.dependencies) {
        dependencies[dependency.name] = dependency;
      }
      return dependencies;
    });
  }
}

/// A constraint that a depending package places on a dependent package has
/// changed.
///
/// This is an abstract class that contains logic for updating the dependency
/// graph once a dependency has changed. Changing the dependency is the
/// responsibility of subclasses.
abstract class ChangeConstraint implements WorkItem {
  Future process(VersionSolver solver);

  void undo(VersionSolver solver);

  Future _processChange(VersionSolver solver, Dependency oldDependency,
      Dependency newDependency) {
    var name = newDependency.name;
    var source = oldDependency.source != null ?
      oldDependency.source : newDependency.source;
    var description = oldDependency.description != null ?
      oldDependency.description : newDependency.description;
    var oldConstraint = oldDependency.constraint;
    var newConstraint = newDependency.constraint;

    // If the package is over-constrained, i.e. the packages depending have
    // disjoint constraints, then try unlocking a depender that's locked by the
    // lockfile. If there are no remaining locked dependencies, throw an error.
    if (newConstraint != null && newConstraint.isEmpty) {
      if (solver.tryUnlockDepender(newDependency)) {
        undo(solver);
        return null;
      }

      throw new DisjointConstraintException(name, newDependency._refs);
    }

    // If this constraint change didn't cause the overall constraint on the
    // package to change, then we don't need to do any further work.
    if (oldConstraint == newConstraint) return null;

    // If the dependency has been cut free from the graph, just remove it.
    if (!newDependency.isDependedOn) {
      solver.enqueue(new ChangeVersion(name, source, description, null));
      return null;
    }

    // If the dependency is on the root package, then we don't need to do
    // anything since it's already at the best version.
    if (name == solver._root.name) {
      solver.enqueue(new ChangeVersion(
          name, source, description, solver._root.version));
      return null;
    }

    // If the dependency is on a package in the lockfile, use the lockfile's
    // version for that package if it's valid given the other constraints.
    var lockedPackage = solver.lockFile.packages[name];
    if (lockedPackage != null) {
      var lockedVersion = lockedPackage.version;
      if (newConstraint.allows(lockedVersion)) {
        solver.enqueue(
            new ChangeVersion(name, source, description, lockedVersion));
        return null;
      }
    }

    // The constraint has changed, so see what the best version of the package
    // that meets the new constraint is.
    return solver.getBestVersion(newDependency).then((best) {
      if (best == null) {
        undo(solver);
      } else if (newDependency.version != best) {
        solver.enqueue(new ChangeVersion(name, source, description, best));
      }
    });
  }
}

/// The constraint given by [ref] is being placed by [depender].
class AddConstraint extends ChangeConstraint {
  /// The package that has the dependency.
  final String depender;

  /// The package being depended on and the constraints being placed on it. The
  /// source, version, and description in this ref are all considered
  /// constraints on the dependent package.
  final PackageRef ref;

  AddConstraint(this.depender, this.ref);

  Future process(VersionSolver solver) {
    log.fine("Adding $depender's constraint $ref.");

    var dependency = solver.getDependency(ref.name);
    var oldDependency = dependency.clone();
    dependency.placeConstraint(depender, ref);
    return _processChange(solver, oldDependency, dependency);
  }

  void undo(VersionSolver solver) {
    solver.getDependency(ref.name).removeConstraint(depender);
  }
}

/// [depender] is no longer placing a constraint on [dependent].
class RemoveConstraint extends ChangeConstraint {
  /// The package that was placing a constraint on [dependent].
  String depender;

  /// The package that was being depended on.
  String dependent;

  /// The constraint that was removed.
  PackageRef _removed;

  RemoveConstraint(this.depender, this.dependent);

  Future process(VersionSolver solver) {
    log.fine("Removing $depender's constraint ($_removed) on $dependent.");

    var dependency = solver.getDependency(dependent);
    var oldDependency = dependency.clone();
    _removed = dependency.removeConstraint(depender);
    return _processChange(solver, oldDependency, dependency);
  }

  void undo(VersionSolver solver) {
    solver.getDependency(dependent).placeConstraint(depender, _removed);
  }
}

/// [package]'s version is no longer constrained by the lockfile.
class UnlockPackage implements WorkItem {
  /// The package being unlocked.
  Dependency package;

  UnlockPackage(this.package);

  Future process(VersionSolver solver) {
    log.fine("Unlocking ${package.name}.");

    solver.lockFile.packages.remove(package.name);
    return solver.getBestVersion(package).then((best) {
      if (best == null) return null;
      solver.enqueue(new ChangeVersion(
          package.name, package.source, package.description, best));
    });
  }
}

// TODO(rnystrom): Instead of always pulling from the source (which will mean
// hitting a server), we should consider caching pubspecs of uninstalled
// packages in the system cache.
/// Maintains a cache of previously-loaded pubspecs. Used to avoid requesting
/// the same pubspec from the server repeatedly.
class PubspecCache {
  final SourceRegistry _sources;
  final Map<PackageId, Pubspec> _pubspecs;

  PubspecCache(this._sources)
      : _pubspecs = new Map<PackageId, Pubspec>();

  /// Caches [pubspec] as the [Pubspec] for the package identified by [id].
  void cache(PackageId id, Pubspec pubspec) {
    _pubspecs[id] = pubspec;
  }

  /// Loads the pubspec for the package identified by [id].
  Future<Pubspec> load(PackageId id) {
    // Complete immediately if it's already cached.
    if (_pubspecs.containsKey(id)) {
      return new Future<Pubspec>.immediate(_pubspecs[id]);
    }

    return id.describe().then((pubspec) {
      // Cache it.
      _pubspecs[id] = pubspec;
      return pubspec;
    });
  }
}

/// Describes one [Package] in the [DependencyGraph] and keeps track of which
/// packages depend on it and what constraints they place on it.
class Dependency {
  /// The name of the this dependency's package.
  final String name;

  /// The [PackageRefs] that represent constraints that depending packages have
  /// placed on this one.
  final Map<String, PackageRef> _refs;

  /// The currently-selected best version for this dependency.
  Version version;

  /// Whether this dependency should always select the latest version.
  bool useLatestVersion = false;

  /// Gets whether or not any other packages are currently depending on this
  /// one. If `false`, then it means this package is not part of the dependency
  /// graph and should be omitted.
  bool get isDependedOn => !_refs.isEmpty;

  /// The names of all the packages that depend on this dependency.
  Iterable<String> get dependers => _refs.keys;

  /// Gets the overall constraint that all packages are placing on this one.
  /// If no packages have a constraint on this one (which can happen when this
  /// package is in the process of being added to the graph), returns `null`.
  VersionConstraint get constraint {
    if (_refs.isEmpty) return null;
    return new VersionConstraint.intersection(
        _refs.values.mappedBy((ref) => ref.constraint));
  }

  /// The source of this dependency's package.
  Source get source {
     var canonical = _canonicalRef();
     if (canonical == null) return null;
     return canonical.source;
  }

  /// The description of this dependency's package.
  get description {
     var canonical = _canonicalRef();
     if (canonical == null) return null;
     return canonical.description;
  }

  /// Return the PackageRef that has the canonical source and description for
  /// this package. If any dependency requires that this package come from a
  /// [RootSource], that will be used; otherwise, it will be the source and
  /// description that all dependencies agree upon.
  PackageRef _canonicalRef() {
    if (_refs.isEmpty) return null;
    var refs = _refs.values;
    for (var ref in refs) {
      if (ref is RootSource) return ref;
    }
    return refs.first;
  }

  Dependency(this.name)
      : _refs = <String, PackageRef>{};

  Dependency._clone(Dependency other)
      : name = other.name,
        version = other.version,
        _refs = new Map<String, PackageRef>.from(other._refs);

  /// Creates a copy of this dependency.
  Dependency clone() => new Dependency._clone(this);

  /// Return a list of available versions for this dependency.
  Future<List<Version>> getVersions() => source.getVersions(name, description);

  /// Places [ref] as a constraint from [package] onto this.
  void placeConstraint(String package, PackageRef ref) {
    var requiredDepender = _requiredDepender();
    if (requiredDepender != null) {
      var required = _refs[requiredDepender];
      if (required.source.name != ref.source.name) {
        throw new SourceMismatchException(name,
            requiredDepender, required.source, package, ref.source);
      } else if (!required.source.descriptionsEqual(
                     required.description, ref.description)) {
        throw new DescriptionMismatchException(name,
            requiredDepender, required.description, package, ref.description);
      }
    }

    _refs[package] = ref;
  }

  /// Returns the name of a package whose constraint source and description
  /// all other constraints must match. Returns null if there are no
  /// requirements on new constraints.
  String _requiredDepender() {
    if (_refs.isEmpty) return null;

    var dependers = _refs.keys.toList();
    if (dependers.length == 1) {
      var depender = dependers[0];
      if (_refs[depender].source is RootSource) return null;
      return depender;
    }

    return dependers[1];
  }

  /// Removes the constraint from [package] onto this.
  PackageRef removeConstraint(String package) => _refs.remove(package);
}

/// Exception thrown when the [VersionConstraint] used to match a package is
/// valid (i.e. non-empty), but there are no released versions of the package
/// that fit that constraint.
class NoVersionException implements Exception {
  final String package;
  final VersionConstraint constraint;
  final Map<String, PackageRef> _dependencies;

  NoVersionException(this.package, this.constraint, this._dependencies);

  String toString() {
    var buffer = new StringBuffer();
    buffer.add("Package '$package' has no versions that match $constraint "
        "derived from:\n");

    var keys = new List.from(_dependencies.keys);
    keys.sort();

    for (var key in keys) {
      buffer.add("- '$key' depends on version "
          "${_dependencies[key].constraint}\n");
    }

    return buffer.toString();
  }
}

// TODO(rnystrom): Report the list of depending packages and their constraints.
/// Exception thrown when the most recent version of [package] must be selected,
/// but doesn't match the [VersionConstraint] imposed on the package.
class CouldNotUpdateException implements Exception {
  final String package;
  final VersionConstraint constraint;
  final Version best;

  CouldNotUpdateException(this.package, this.constraint, this.best);

  String toString() =>
      "The latest version of '$package', $best, does not match $constraint.";
}

/// Exception thrown when the [VersionConstraint] used to match a package is
/// the empty set: in other words, multiple packages depend on it and have
/// conflicting constraints that have no overlap.
class DisjointConstraintException implements Exception {
  final String package;
  final Map<String, PackageRef> _dependencies;

  DisjointConstraintException(this.package, this._dependencies);

  String toString() {
    var buffer = new StringBuffer();
    buffer.add("Incompatible version constraints on '$package':\n");

    var keys = new List.from(_dependencies.keys);
    keys.sort();

    for (var key in keys) {
      buffer.add("- '$key' depends on version "
          "${_dependencies[key].constraint}\n");
    }

    return buffer.toString();
  }
}

/// Exception thrown when the [VersionSolver] fails to find a solution after a
/// certain number of iterations.
class CouldNotSolveException implements Exception {
  CouldNotSolveException();

  String toString() =>
      "Could not find a solution that met all version constraints.";
}

/// Exception thrown when two packages with the same name but different sources
/// are depended upon.
class SourceMismatchException implements Exception {
  final String package;
  final String depender1;
  final Source source1;
  final String depender2;
  final Source source2;

  SourceMismatchException(this.package, this.depender1, this.source1,
      this.depender2, this.source2);

  String toString() {
    return "Incompatible dependencies on '$package':\n"
        "- '$depender1' depends on it from source '$source1'\n"
        "- '$depender2' depends on it from source '$source2'";
  }
}

/// Exception thrown when two packages with the same name and source but
/// different descriptions are depended upon.
class DescriptionMismatchException implements Exception {
  final String package;
  final String depender1;
  final description1;
  final String depender2;
  final description2;

  DescriptionMismatchException(this.package, this.depender1, this.description1,
      this.depender2, this.description2);

  String toString() {
    // TODO(nweiz): Dump descriptions to YAML when that's supported.
    return "Incompatible dependencies on '$package':\n"
        "- '$depender1' depends on it with description "
        "${json.stringify(description1)}\n"
        "- '$depender2' depends on it with description "
        "${json.stringify(description2)}";
  }
}
