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

library pub.solver.dependency_queue;

import 'dart:async';
import 'dart:collection' show Queue;

import '../log.dart' as log;
import '../package.dart';
import 'backtracking_solver.dart';

/// A queue of one package's dependencies, ordered by how the solver should
/// traverse them.
///
/// It prefers locked versions so that they stay locked if possible. Then it
/// prefers a currently selected package so that it only has to consider a
/// single version.
///
/// After that, it orders the remaining packages by the number of versions they
/// have so that packages with fewer versions are solved first. (If two
/// packages have the same number of versions, they are sorted alphabetically
/// just to be deterministic.)
///
/// Critically, this queue will *not* sort the dependencies by number of
/// versions until actually needed. This ensures we don't do any network
/// requests until we actually need to. In particular, it means that solving
/// a package graph with an already up-to-date lockfile will do no network
/// requests.
class DependencyQueue {
  final BacktrackingSolver _solver;

  /// The dependencies for packages that have already been selected.
  final Queue<PackageDep> _presorted;

  /// The dependencies on the remaining packages.
  ///
  /// This is lazily sorted right before the first item is requested.
  final List<PackageDep> _remaining;

  bool _isSorted = false;

  /// Gets whether there are any dependencies left to iterate over.
  bool get isEmpty => _presorted.isEmpty && _remaining.isEmpty;

  /// The pending [Future] while the remaining dependencies are being sorted.
  ///
  /// This will only be non-null while a sort is in progress.
  Future _sortFuture;

  factory DependencyQueue(BacktrackingSolver solver,
      Iterable<PackageDep> deps) {
    // Separate out the presorted ones.
    var presorted = <PackageDep>[];
    var remaining = <PackageDep>[];

    for (var dep in deps) {
      // Selected or locked packages come first.
      if (solver.getSelected(dep.name) != null ||
          solver.getLocked(dep.name) != null) {
        presorted.add(dep);
      } else {
        remaining.add(dep);
      }
    }

    // Sort the selected/locked packages by name just to ensure the solver is
    // deterministic.
    presorted.sort((a, b) => a.name.compareTo(b.name));

    return new DependencyQueue._(solver, new Queue<PackageDep>.from(presorted),
        remaining);
  }

  DependencyQueue._(this._solver, this._presorted, this._remaining);

  /// Emits the next dependency in priority order.
  ///
  /// It is an error to call this if [isEmpty] returns `true`. Note that this
  /// function is *not* re-entrant. You should only advance after the previous
  /// advance has completed.
  Future<PackageDep> advance() {
    // Emit the sorted ones first.
    if (_presorted.isNotEmpty) {
      return new Future.value(_presorted.removeFirst());
    }

    // Sort the remaining packages when we need the first one.
    if (!_isSorted) return _sort().then((_) => _remaining.removeAt(0));

    return new Future.value(_remaining.removeAt(0));
  }

  /// Sorts the unselected packages by number of versions and name.
  Future _sort() {
    // Sorting is not re-entrant.
    assert(_sortFuture == null);

    _sortFuture = Future.wait(_remaining.map(_getNumVersions)).then((versions) {
      _sortFuture = null;

      // Map deps to the number of versions they have.
      var versionMap = new Map.fromIterables(_remaining, versions);

      // Sort in best-first order to minimize backtracking.
      _remaining.sort((a, b) {
        // Traverse into packages with fewer versions since they will lead to
        // less backtracking.
        if (versionMap[a] != versionMap[b]) {
          return versionMap[a].compareTo(versionMap[b]);
        }

        // Otherwise, just sort by name so that it's deterministic.
        return a.name.compareTo(b.name);
      });

      _isSorted = true;
    });

    return _sortFuture;
  }

  /// Given a dependency, returns a future that completes to the number of
  /// versions available for it.
  Future<int> _getNumVersions(PackageDep dep) {
    // There is only ever one version of the root package.
    if (dep.isRoot) {
      return new Future.value(1);
    }

    return _solver.cache.getVersions(dep.toRef()).then((versions) {
      return versions.length;
    }).catchError((error, trace) {
      // If it fails for any reason, just treat that as no versions. This
      // will sort this reference higher so that we can traverse into it
      // and report the error more properly.
      log.solver("Could not get versions for $dep:\n$error\n\n$trace");
      return 0;
    });
  }
}
