// Copyright (c) 2022, 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 '../../context.dart';

import '../collection_equality.dart';
import 'core.dart';

extension IterableChecks<T> on Subject<Iterable<T>> {
  Subject<int> get length => has((l) => l.length, 'length');

  Subject<T> get first => context.nest(() => ['has first element'], (actual) {
        final iterator = actual.iterator;
        if (!iterator.moveNext()) {
          return Extracted.rejection(which: ['has no elements']);
        }
        return Extracted.value(iterator.current);
      });

  Subject<T> get last => context.nest(() => ['has last element'], (actual) {
        final iterator = actual.iterator;
        if (!iterator.moveNext()) {
          return Extracted.rejection(which: ['has no elements']);
        }
        var current = iterator.current;
        while (iterator.moveNext()) {
          current = iterator.current;
        }
        return Extracted.value(current);
      });

  Subject<T> get single => context.nest(() => ['has single element'], (actual) {
        final iterator = actual.iterator;
        if (!iterator.moveNext()) {
          return Extracted.rejection(which: ['has no elements']);
        }
        final value = iterator.current;
        if (iterator.moveNext()) {
          return Extracted.rejection(which: ['has more than one element']);
        }
        return Extracted.value(value);
      });

  void isEmpty() {
    context.expect(() => const ['is empty'], (actual) {
      if (actual.isEmpty) return null;
      return Rejection(which: ['is not empty']);
    });
  }

  void isNotEmpty() {
    context.expect(() => const ['is not empty'], (actual) {
      if (actual.isNotEmpty) return null;
      return Rejection(which: ['is empty']);
    });
  }

  /// Expects that the iterable contains [element] according to
  /// [Iterable.contains].
  void contains(T element) {
    context.expect(() {
      return prefixFirst('contains ', literal(element));
    }, (actual) {
      if (actual.isEmpty) return Rejection(actual: ['an empty iterable']);
      if (actual.contains(element)) return null;
      return Rejection(
          which: prefixFirst('does not contain ', literal(element)));
    });
  }

  /// Expects that the iterable contains a value matching each expected value
  /// from [elements] in the given order, with any extra elements between
  /// them.
  ///
  /// For example, the following will succeed:
  ///
  /// ```dart
  /// check([1, 0, 2, 0, 3]).containsInOrder([1, 2, 3]);
  /// ```
  ///
  /// Values in [elements] may be a `T`, a `Condition<T>`, or a
  /// `Condition<Object?>`. If an expectation is a condition callback it will be
  /// checked against the actual values, and any other expectations, including
  /// those that are not a `T` or a condition callback, will be compared with
  /// the equality operator.
  ///
  /// ```dart
  /// check([1, 0, 2, 0, 3])
  ///   .containsInOrder([1, (Subject<int> v) => v.isGreaterThan(1), 3]);
  /// ```
  @Deprecated('Use `containsEqualInOrder` for expectations with values compared'
      ' with `==` or `containsMatchingInOrder` for other expectations')
  void containsInOrder(Iterable<Object?> elements) {
    context.expect(() => prefixFirst('contains, in order: ', literal(elements)),
        (actual) {
      final expected = elements.toList();
      if (expected.isEmpty) {
        throw ArgumentError('expected may not be empty');
      }
      var expectedIndex = 0;
      for (final element in actual) {
        final currentExpected = expected[expectedIndex];
        final matches = currentExpected is Condition<T>
            ? softCheck(element, currentExpected) == null
            : currentExpected is Condition<dynamic>
                ? softCheck(element, currentExpected) == null
                : currentExpected == element;
        if (matches && ++expectedIndex >= expected.length) return null;
      }
      return Rejection(which: [
        ...prefixFirst(
            'did not have an element matching the expectation at index '
            '$expectedIndex ',
            literal(expected[expectedIndex])),
      ]);
    });
  }

  /// Expects that the iterable contains a value matching each condition in
  /// [conditions] in the given order, with any extra elements between them.
  ///
  /// For example, the following will succeed:
  ///
  /// ```dart
  /// check([1, 10, 2, 10, 3]).containsMatchingInOrder([
  ///   (it) => it.isLessThan(2),
  ///   (it) => it.isLessThan(3),
  ///   (it) => it.isLessThan(4),
  /// ]);
  /// ```
  void containsMatchingInOrder(Iterable<Condition<T>> conditions) {
    context
        .expect(() => prefixFirst('contains, in order: ', literal(conditions)),
            (actual) {
      final expected = conditions.toList();
      if (expected.isEmpty) {
        throw ArgumentError('expected may not be empty');
      }
      var expectedIndex = 0;
      for (final element in actual) {
        final currentExpected = expected[expectedIndex];
        final matches = softCheck(element, currentExpected) == null;
        if (matches && ++expectedIndex >= expected.length) return null;
      }
      return Rejection(which: [
        ...prefixFirst(
            'did not have an element matching the expectation at index '
            '$expectedIndex ',
            literal(expected[expectedIndex])),
      ]);
    });
  }

  /// Expects that the iterable contains a value equals to each expected value
  /// from [elements] in the given order, with any extra elements between
  /// them.
  ///
  /// For example, the following will succeed:
  ///
  /// ```dart
  /// check([1, 0, 2, 0, 3]).containsInOrder([1, 2, 3]);
  /// ```
  ///
  /// Values, will be compared with the equality operator.
  void containsEqualInOrder(Iterable<T> elements) {
    context.expect(() => prefixFirst('contains, in order: ', literal(elements)),
        (actual) {
      final expected = elements.toList();
      if (expected.isEmpty) {
        throw ArgumentError('expected may not be empty');
      }
      var expectedIndex = 0;
      for (final element in actual) {
        final currentExpected = expected[expectedIndex];
        final matches = currentExpected == element;
        if (matches && ++expectedIndex >= expected.length) return null;
      }
      return Rejection(which: [
        ...prefixFirst(
            'did not have an element equal to the expectation at index '
            '$expectedIndex ',
            literal(expected[expectedIndex])),
      ]);
    });
  }

  /// Expects that the iterable contains at least on element such that
  /// [elementCondition] is satisfied.
  void any(Condition<T> elementCondition) {
    context.expect(() {
      final conditionDescription = describe(elementCondition);
      assert(conditionDescription.isNotEmpty);
      return [
        'contains a value that:',
        ...conditionDescription,
      ];
    }, (actual) {
      if (actual.isEmpty) return Rejection(actual: ['an empty iterable']);
      for (var e in actual) {
        if (softCheck(e, elementCondition) == null) return null;
      }
      return Rejection(which: ['Contains no matching element']);
    });
  }

  /// Expects there are no elements in the iterable which fail to satisfy
  /// [elementCondition].
  ///
  /// Empty iterables will pass always pass this expectation.
  void every(Condition<T> elementCondition) {
    context.expect(() {
      final conditionDescription = describe(elementCondition);
      assert(conditionDescription.isNotEmpty);
      return [
        'only has values that:',
        ...conditionDescription,
      ];
    }, (actual) {
      final iterator = actual.iterator;
      for (var i = 0; iterator.moveNext(); i++) {
        final element = iterator.current;
        final failure = softCheck(element, elementCondition);
        if (failure == null) continue;
        final which = failure.rejection.which;
        return Rejection(which: [
          'has an element at index $i that:',
          ...indent(failure.detail.actual.skip(1)),
          ...indent(prefixFirst('Actual: ', failure.rejection.actual),
              failure.detail.depth + 1),
          if (which != null && which.isNotEmpty)
            ...indent(prefixFirst('Which: ', which), failure.detail.depth + 1),
        ]);
      }
      return null;
    });
  }

  /// Expects that the iterable contains elements that are deeply equal to the
  /// elements of [expected].
  ///
  /// {@macro deep_collection_equals}
  void deepEquals(Iterable<Object?> expected) => context
          .expect(() => prefixFirst('is deeply equal to ', literal(expected)),
              (actual) {
        final which = deepCollectionEquals(actual, expected);
        if (which == null) return null;
        return Rejection(which: which);
      });

  /// Expects that the iterable contains elements which equal those of
  /// [expected] in any order.
  ///
  /// Should not be used for very large collections, runtime is O(n^2.5) in the
  /// worst case where the iterables contain many equal elements, and O(n^2) in
  /// more typical cases.
  void unorderedEquals(Iterable<T> expected) {
    context.expect(() => prefixFirst('unordered equals ', literal(expected)),
        (actual) {
      final which = unorderedCompare(
        actual,
        expected,
        (actual, expected) => expected == actual,
        (expected, index, count) => [
          ...prefixFirst(
              'has no element equal to the expected element at index '
              '$index: ',
              literal(expected)),
          if (count > 1) 'or ${count - 1} other elements',
        ],
        (actual, index, count) => [
          ...prefixFirst(
              'has an unexpected element at index $index: ', literal(actual)),
          if (count > 1) 'and ${count - 1} other unexpected elements',
        ],
      );
      if (which == null) return null;
      return Rejection(which: which);
    });
  }

  /// Expects that the iterable contains elements which match all conditions of
  /// [expected] in any order.
  ///
  /// Should not be used for very large collections, runtime is O(n^2.5) in the
  /// worst case where conditions match many elements, and O(n^2) in more
  /// typical cases.
  void unorderedMatches(Iterable<Condition<T>> expected) {
    context.expect(() => prefixFirst('unordered matches ', literal(expected)),
        (actual) {
      final which = unorderedCompare(
        actual,
        expected,
        (actual, expected) => softCheck(actual, expected) == null,
        (expected, index, count) => [
          'has no element matching the condition at index $index:',
          ...describe(expected),
          if (count > 1) 'or ${count - 1} other conditions',
        ],
        (actual, index, count) => [
          ...prefixFirst(
              'has an unmatched element at index $index: ', literal(actual)),
          if (count > 1) 'and ${count - 1} other unmatched elements',
        ],
      );
      if (which == null) return null;
      return Rejection(which: which);
    });
  }

  /// Expects that the iterable contains elements that correspond by the
  /// [elementCondition] exactly to each element in [expected].
  ///
  /// Fails if the iterable has a different length than [expected].
  ///
  /// For each element in the iterable, calls [elementCondition] with the
  /// corresponding element from [expected] to get the specific condition for
  /// that index.
  ///
  /// [description] is used in the Expected clause. It should be a predicate
  /// without the object, for example with the description 'is less than' the
  /// full expectation will be: "pairwise is less than $expected"
  @Deprecated('Use `pairwiseMatches`')
  void pairwiseComparesTo<S>(List<S> expected,
          Condition<T> Function(S) elementCondition, String description) =>
      pairwiseMatches(expected, elementCondition, description);

  /// Expects that the iterable contains elements that correspond by the
  /// [elementCondition] exactly to each element in [expected].
  ///
  /// Fails if the iterable has a different length than [expected].
  ///
  /// For each element in the iterable, calls [elementCondition] with the
  /// corresponding element from [expected] to get the specific condition for
  /// that index.
  ///
  /// [description] is used in the Expected clause. It should be a predicate
  /// without the object, for example with the description 'is less than' the
  /// full expectation will be: "pairwise is less than $expected"
  void pairwiseMatches<S>(List<S> expected,
      Condition<T> Function(S) elementCondition, String description) {
    context.expect(() {
      return prefixFirst('pairwise $description ', literal(expected));
    }, (actual) {
      final iterator = actual.iterator;
      for (var i = 0; i < expected.length; i++) {
        final expectedValue = expected[i];
        if (!iterator.moveNext()) {
          return Rejection(which: [
            'has too few elements, there is no element to match at index $i'
          ]);
        }
        final actualValue = iterator.current;
        final failure = softCheck(actualValue, elementCondition(expectedValue));
        if (failure == null) continue;
        final innerDescription = describe<T>(elementCondition(expectedValue));
        final which = failure.rejection.which;
        return Rejection(which: [
          'does not have an element at index $i that:',
          ...innerDescription,
          ...prefixFirst(
              'Actual element at index $i: ', failure.rejection.actual),
          if (which != null) ...prefixFirst('Which: ', which),
        ]);
      }
      if (!iterator.moveNext()) return null;
      return Rejection(which: [
        'has too many elements, expected exactly ${expected.length}'
      ]);
    });
  }
}
