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

import 'package:collection/collection.dart';

import '../exceptions.dart';
import '../log.dart' as log;
import '../package_name.dart';
import '../sdk.dart';
import '../utils.dart';
import 'incompatibility.dart';
import 'incompatibility_cause.dart';

/// An exception indicating that version solving failed.
class SolveFailure implements ApplicationException {
  /// The root incompatibility.
  ///
  /// This will always indicate that the root package is unselectable. That is,
  /// it will have one term, which will be the root package.
  final Incompatibility incompatibility;

  @override
  String get message => toString();

  /// Returns a [PackageNotFoundException] that (transitively) caused this
  /// failure, or `null` if it wasn't caused by a [PackageNotFoundException].
  ///
  /// If multiple [PackageNotFoundException]s caused the error, it's undefined
  /// which one is returned.
  PackageNotFoundException? get packageNotFound {
    for (var incompatibility in incompatibility.externalIncompatibilities) {
      var cause = incompatibility.cause;
      if (cause is PackageNotFoundCause) return cause.exception;
    }
    return null;
  }

  SolveFailure(this.incompatibility)
      : assert(incompatibility.terms.isEmpty ||
            incompatibility.terms.single.package.isRoot);

  /// Describes how [incompatibility] was derived, and thus why version solving
  /// failed.
  @override
  String toString() => _Writer(incompatibility).write();
}

/// A class that writes a human-readable description of the cause of a
/// [SolveFailure].
///
/// See https://github.com/dart-lang/pub/tree/master/doc/solver.md#error-reporting
/// for details on how this algorithm works.
class _Writer {
  /// The root incompatibility.
  final Incompatibility _root;

  /// The number of times each [Incompatibility] appears in [_root]'s derivation
  /// tree.
  ///
  /// When an [Incompatibility] is used in multiple derivations, we need to give
  /// it a number so we can refer back to it later on.
  final _derivations = <Incompatibility, int>{};

  /// The lines in the proof.
  ///
  /// Each line is a message/number pair. The message describes a single
  /// incompatibility, and why its terms are incompatible. The number is
  /// optional and indicates the explicit number that should be associated with
  /// the line so it can be referred to later on.
  final _lines = <Pair<String, int?>>[];

  // A map from incompatibilities to the line numbers that were written for
  // those incompatibilities.
  final _lineNumbers = <Incompatibility, int>{};

  _Writer(this._root) {
    _countDerivations(_root);
  }

  /// Populates [_derivations] for [incompatibility] and its transitive causes.
  void _countDerivations(Incompatibility incompatibility) {
    _derivations.update(incompatibility, (value) => value + 1, ifAbsent: () {
      var cause = incompatibility.cause;
      if (cause is ConflictCause) {
        _countDerivations(cause.conflict);
        _countDerivations(cause.other);
      }
      return 1;
    });
  }

  String write() {
    var buffer = StringBuffer();

    // SDKs whose version constraints weren't matched.
    var sdkConstraintCauses = <Sdk>{};

    // SDKs implicated in any way in the solve failure.
    var sdkCauses = <Sdk>{};

    for (var incompatibility in _root.externalIncompatibilities) {
      var cause = incompatibility.cause;
      if (cause is PackageNotFoundCause) {
        var sdk = cause.sdk;
        if (sdk != null) {
          sdkCauses.add(sdk);
        }
      } else if (cause is SdkCause) {
        sdkCauses.add(cause.sdk);
        sdkConstraintCauses.add(cause.sdk);
      }
    }

    // If the failure was caused in part by unsatisfied SDK constraints,
    // indicate the actual versions so we don't have to list them (possibly
    // multiple times) in the main body of the error message.
    //
    // Iterate through [sdks] to ensure that SDKs versions are printed in a
    // consistent order
    var wroteLine = false;
    for (var sdk in sdks.values) {
      if (!sdkConstraintCauses.contains(sdk)) continue;
      if (!sdk.isAvailable) continue;
      wroteLine = true;
      buffer.writeln('The current ${sdk.name} SDK version is ${sdk.version}.');
    }
    if (wroteLine) buffer.writeln();

    if (_root.cause is ConflictCause) {
      _visit(_root, const {});
    } else {
      _write(_root, 'Because $_root, version solving failed.');
    }

    // Only add line numbers if the derivation actually needs to refer to a line
    // by number.
    var padding =
        _lineNumbers.isEmpty ? 0 : '(${_lineNumbers.values.last}) '.length;

    var lastWasEmpty = false;
    for (var line in _lines) {
      var message = line.first;
      if (message.isEmpty) {
        if (!lastWasEmpty) buffer.writeln();
        lastWasEmpty = true;
        continue;
      } else {
        lastWasEmpty = false;
      }

      var number = line.last;
      if (number != null) {
        message = '($number)'.padRight(padding) + message;
      } else {
        message = ' ' * padding + message;
      }

      buffer.writeln(wordWrap(message, prefix: ' ' * (padding + 2)));
    }

    // Iterate through [sdks] to ensure that SDKs versions are printed in a
    // consistent order
    for (var sdk in sdks.values) {
      if (!sdkCauses.contains(sdk)) continue;
      if (sdk.isAvailable) continue;
      if (sdk.installMessage == null) continue;
      buffer.writeln();
      buffer.writeln(sdk.installMessage);
    }

    return buffer.toString();
  }

  /// Writes [message] to [_lines].
  ///
  /// The [message] should describe [incompatibility] and how it was derived (if
  /// applicable). If [numbered] is true, this will associate a line number with
  /// [incompatibility] and [message] so that the message can be easily referred
  /// to later.
  void _write(Incompatibility incompatibility, String message,
      {bool numbered = false}) {
    if (numbered) {
      var number = _lineNumbers.length + 1;
      _lineNumbers[incompatibility] = number;
      _lines.add(Pair(message, number));
    } else {
      _lines.add(Pair(message, null));
    }
  }

  /// Writes a proof of [incompatibility] to [_lines].
  ///
  /// If [conclusion] is `true`, [incompatibility] represents the last of a
  /// linear series of derivations. It should be phrased accordingly and given a
  /// line number.
  ///
  /// The [detailsForIncompatibility] controls the amount of detail that should
  /// be written for each package when converting [incompatibility] to a string.
  void _visit(Incompatibility incompatibility,
      Map<String, PackageDetail> detailsForIncompatibility,
      {bool conclusion = false}) {
    // Add explicit numbers for incompatibilities that are written far away
    // from their successors or that are used for multiple derivations.
    var numbered = conclusion || _derivations[incompatibility]! > 1;
    var conjunction = conclusion || incompatibility == _root ? 'So,' : 'And';
    var incompatibilityString =
        log.bold(incompatibility.toString(detailsForIncompatibility));

    var conflictClause = incompatibility.cause as ConflictCause;
    var detailsForCause = _detailsForCause(conflictClause);
    var cause = conflictClause.conflict.cause;
    var otherCause = conflictClause.other.cause;
    if (cause is ConflictCause && otherCause is ConflictCause) {
      var conflictLine = _lineNumbers[conflictClause.conflict];
      var otherLine = _lineNumbers[conflictClause.other];
      if (conflictLine != null && otherLine != null) {
        _write(
            incompatibility,
            'Because ' +
                conflictClause.conflict.andToString(conflictClause.other,
                    detailsForCause, conflictLine, otherLine) +
                ', $incompatibilityString.',
            numbered: numbered);
      } else if (conflictLine != null || otherLine != null) {
        Incompatibility withLine;
        Incompatibility withoutLine;
        int line;
        if (conflictLine != null) {
          withLine = conflictClause.conflict;
          withoutLine = conflictClause.other;
          line = conflictLine;
        } else {
          withLine = conflictClause.other;
          withoutLine = conflictClause.conflict;
          line = otherLine!;
        }

        _visit(withoutLine, detailsForCause);
        _write(
            incompatibility,
            '$conjunction because ${withLine.toString(detailsForCause)} '
            '($line), $incompatibilityString.',
            numbered: numbered);
      } else {
        var singleLineConflict = _isSingleLine(cause);
        var singleLineOther = _isSingleLine(otherCause);
        if (singleLineOther || singleLineConflict) {
          var first =
              singleLineOther ? conflictClause.conflict : conflictClause.other;
          var second =
              singleLineOther ? conflictClause.other : conflictClause.conflict;
          _visit(first, detailsForCause);
          _visit(second, detailsForCause);
          _write(incompatibility, 'Thus, $incompatibilityString.',
              numbered: numbered);
        } else {
          _visit(conflictClause.conflict, {}, conclusion: true);
          _lines.add(Pair('', null));

          _visit(conflictClause.other, detailsForCause);
          _write(
              incompatibility,
              '$conjunction because '
              '${conflictClause.conflict.toString(detailsForCause)} '
              '(${_lineNumbers[conflictClause.conflict]}), '
              '$incompatibilityString.',
              numbered: numbered);
        }
      }
    } else if (cause is ConflictCause || otherCause is ConflictCause) {
      var derived = cause is ConflictCause
          ? conflictClause.conflict
          : conflictClause.other;
      var ext = cause is ConflictCause
          ? conflictClause.other
          : conflictClause.conflict;

      var derivedLine = _lineNumbers[derived];
      if (derivedLine != null) {
        _write(
            incompatibility,
            'Because ' +
                ext.andToString(derived, detailsForCause, null, derivedLine) +
                ', $incompatibilityString.',
            numbered: numbered);
      } else if (_isCollapsible(derived)) {
        var derivedCause = derived.cause as ConflictCause;
        var collapsedDerived = derivedCause.conflict.cause is ConflictCause
            ? derivedCause.conflict
            : derivedCause.other;
        var collapsedExt = derivedCause.conflict.cause is ConflictCause
            ? derivedCause.other
            : derivedCause.conflict;

        detailsForCause = mergeMaps(
            detailsForCause, _detailsForCause(derivedCause),
            value: (detail1, detail2) => detail1.max(detail2));

        _visit(collapsedDerived, detailsForCause);
        _write(
            incompatibility,
            '$conjunction because '
            '${collapsedExt.andToString(ext, detailsForCause)}, '
            '$incompatibilityString.',
            numbered: numbered);
      } else {
        _visit(derived, detailsForCause);
        _write(
            incompatibility,
            '$conjunction because ${ext.toString(detailsForCause)}, '
            '$incompatibilityString.',
            numbered: numbered);
      }
    } else {
      _write(
          incompatibility,
          'Because '
          '${conflictClause.conflict.andToString(conflictClause.other, detailsForCause)}, '
          '$incompatibilityString.',
          numbered: numbered);
    }
  }

  /// Returns whether we can collapse the derivation of [incompatibility].
  ///
  /// If [incompatibility] is only used to derive one other incompatibility,
  /// it may make sense to skip that derivation and just derive the second
  /// incompatibility directly from three causes. This is usually clear enough
  /// to the user, and makes the proof much terser.
  ///
  /// For example, instead of writing
  ///
  ///     ... foo ^1.0.0 requires bar ^1.0.0.
  ///     And, because bar ^1.0.0 depends on baz ^1.0.0, foo ^1.0.0 requires
  ///       baz ^1.0.0.
  ///     And, because baz ^1.0.0 depends on qux ^1.0.0, foo ^1.0.0 requires
  ///       qux ^1.0.0.
  ///     ...
  ///
  /// we collapse the two derivations into a single line and write
  ///
  ///     ... foo ^1.0.0 requires bar ^1.0.0.
  ///     And, because bar ^1.0.0 depends on baz ^1.0.0 which depends on
  ///       qux ^1.0.0, foo ^1.0.0 requires qux ^1.0.0.
  ///     ...
  ///
  /// If this returns `true`, [incompatibility] has one external predecessor
  /// and one derived predecessor.
  bool _isCollapsible(Incompatibility incompatibility) {
    // If [incompatibility] is used for multiple derivations, it will need a
    // line number and so will need to be written explicitly.
    if (_derivations[incompatibility]! > 1) return false;

    var cause = incompatibility.cause as ConflictCause;
    // If [incompatibility] is derived from two derived incompatibilities,
    // there are too many transitive causes to display concisely.
    if (cause.conflict.cause is ConflictCause &&
        cause.other.cause is ConflictCause) {
      return false;
    }

    // If [incompatibility] is derived from two external incompatibilities, it
    // tends to be confusing to collapse it.
    if (cause.conflict.cause is! ConflictCause &&
        cause.other.cause is! ConflictCause) {
      return false;
    }

    // If [incompatibility]'s internal cause is numbered, collapsing it would
    // get too noisy.
    var complex =
        cause.conflict.cause is ConflictCause ? cause.conflict : cause.other;
    return !_lineNumbers.containsKey(complex);
  }

  // Returns whether or not [cause]'s incompatibility can be represented in a
  // single line without requiring a multi-line derivation.
  bool _isSingleLine(ConflictCause cause) =>
      cause.conflict.cause is! ConflictCause &&
      cause.other.cause is! ConflictCause;

  /// Returns the amount of detail needed for each package to accurately
  /// describe [cause].
  ///
  /// If the same package name appears in both of [cause]'s incompatibilities
  /// but each has a different source, those incompatibilities should explicitly
  /// print their sources, and similarly for differing descriptions.
  Map<String, PackageDetail> _detailsForCause(ConflictCause cause) {
    var conflictPackages = <String, PackageName>{};
    for (var term in cause.conflict.terms) {
      if (term.package.isRoot) continue;
      conflictPackages[term.package.name] = term.package;
    }

    var details = <String, PackageDetail>{};
    for (var term in cause.other.terms) {
      var conflictPackage = conflictPackages[term.package.name];
      if (term.package.isRoot) continue;
      if (conflictPackage == null) continue;
      if (conflictPackage.source != term.package.source) {
        details[term.package.name] =
            const PackageDetail(showSource: true, showVersion: false);
      } else if (!conflictPackage.samePackage(term.package)) {
        details[term.package.name] =
            const PackageDetail(showDescription: true, showVersion: false);
      }
    }

    return details;
  }
}
