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

part of matcher;

/**
 * Returns a matcher which matches [Iterable]s in which all elements
 * match the given [matcher].
 */
Matcher everyElement(matcher) => new _EveryElement(wrapMatcher(matcher));

class _EveryElement extends _IterableMatcher {
  Matcher _matcher;

  _EveryElement(Matcher this._matcher);

  bool matches(item, MatchState matchState) {
    if (item is! Iterable) {
      return false;
    }
    var i = 0;
    for (var element in item) {
      if (!_matcher.matches(element, matchState)) {
        matchState.state = {
            'index': i,
            'element': element,
            'state': matchState.state
        };
        return false;
      }
      ++i;
    }
    return true;
  }

  Description describe(Description description) =>
      description.add('every element ').addDescriptionOf(_matcher);

  Description describeMismatch(item, Description mismatchDescription,
                               MatchState matchState, bool verbose) {
    if (matchState.state != null) {
      var index = matchState.state['index'];
      var element = matchState.state['element'];
      mismatchDescription.add('position $index ');
      return _matcher.describeMismatch(element, mismatchDescription,
            matchState.state['state'], verbose);
    }
    return super.describeMismatch(item, mismatchDescription,
          matchState, verbose);
  }
}

/**
 * Returns a matcher which matches [Iterable]s in which at least one
 * element matches the given [matcher].
 */
Matcher someElement(matcher) => new _SomeElement(wrapMatcher(matcher));

class _SomeElement extends _IterableMatcher {
  Matcher _matcher;

  _SomeElement(this._matcher);

  bool matches(item, MatchState matchState) {
    return item.any((e) => _matcher.matches(e, matchState));
  }

  Description describe(Description description) =>
      description.add('some element ').addDescriptionOf(_matcher);
}

/**
 * Returns a matcher which matches [Iterable]s that have the same
 * length and the same elements as [expected], and in the same order.
 * This is equivalent to equals but does not recurse.
 */

Matcher orderedEquals(Iterable expected) => new _OrderedEquals(expected);

class _OrderedEquals extends BaseMatcher {
  final Iterable _expected;
  Matcher _matcher;

  _OrderedEquals(this._expected) {
    _matcher = equals(_expected, 1);
  }

  bool matches(item, MatchState matchState) =>
      (item is Iterable) && _matcher.matches(item, matchState);

  Description describe(Description description) =>
      description.add('equals ').addDescriptionOf(_expected).add(' ordered');

  Description describeMismatch(item, Description mismatchDescription,
                               MatchState matchState, bool verbose) {
    if (item is !Iterable) {
      return mismatchDescription.add('not an Iterable');
    } else {
      return _matcher.describeMismatch(item, mismatchDescription,
          matchState, verbose);
    }
  }
}
/**
 * Returns a matcher which matches [Iterable]s that have the same
 * length and the same elements as [expected], but not necessarily in
 * the same order. Note that this is O(n^2) so should only be used on
 * small objects.
 */
Matcher unorderedEquals(Iterable expected) =>
    new _UnorderedEquals(expected);

class _UnorderedEquals extends BaseMatcher {
  Iterable _expected;

  _UnorderedEquals(Iterable this._expected);

  String _test(item) {
    if (item is !Iterable) {
      return 'not iterable';
    }
    // Check the lengths are the same.
    var expectedLength = _expected.length;
    var actualLength = item.length;
    if (expectedLength > actualLength) {
      return 'has too few elements (${actualLength} < ${expectedLength})';
    } else if (expectedLength < actualLength) {
      return 'has too many elements (${actualLength} > ${expectedLength})';
    }
    List<bool> matched = new List<bool>(actualLength);
    for (var i = 0; i < actualLength; i++) {
      matched[i] = false;
    }
    var expectedPosition = 0;
    for (var expectedElement in _expected) {
      var actualPosition = 0;
      var gotMatch = false;
      for (var actualElement in item) {
        if (!matched[actualPosition]) {
          if (expectedElement == actualElement) {
            matched[actualPosition] = gotMatch = true;
            break;
          }
        }
        ++actualPosition;
      }
      if (!gotMatch) {
        Description reason = new StringDescription();
        reason.add('has no match for element ').
            addDescriptionOf(expectedElement).
            add(' at position ${expectedPosition}');
        return reason.toString();
      }
      ++expectedPosition;
    }
    return null;
  }

  bool matches(item, MatchState mismatchState) => (_test(item) == null);

  Description describe(Description description) =>
      description.add('equals ').addDescriptionOf(_expected).add(' unordered');

  Description describeMismatch(item, Description mismatchDescription,
                               MatchState matchState, bool verbose) =>
      mismatchDescription.add(_test(item));
}

/**
 * Iterable matchers match against [Iterable]s. We add this intermediate
 * class to give better mismatch error messages than the base Matcher class.
 */
abstract class _IterableMatcher extends BaseMatcher {
  const _IterableMatcher();
  Description describeMismatch(item, Description mismatchDescription,
                               MatchState matchState, bool verbose) {
    if (item is! Iterable) {
      return mismatchDescription.
          addDescriptionOf(item).
          add(' not an Iterable');
    } else {
      return super.describeMismatch(item, mismatchDescription, matchState,
        verbose);
    }
  }
}

/**
 * A pairwise matcher for iterable. You can pass an arbitrary [comparator]
 * function that takes an expected and actual argument which will be applied
 * to each pair in order. [description]  should be a meaningful name for
 * the comparator.
 */
Matcher pairwiseCompare(Iterable expected, Function comparator,
    String description) =>
        new _PairwiseCompare(expected, comparator, description);

class _PairwiseCompare extends _IterableMatcher {
  Iterable _expected;
  Function _comparator;
  String _description;

  _PairwiseCompare(this._expected, this._comparator, this._description);

  bool matches(item, MatchState matchState) {
    if (item is! Iterable) return false;
    if (item.length != _expected.length) return false;
    var iterator = item.iterator;
    var i = 0;
    for (var e in _expected) {
      iterator.moveNext();
      if (!_comparator(e, iterator.current)) {
        matchState.state = {
            'index': i,
            'expected': e,
            'actual' : iterator.current,
            'state': matchState.state
        };
        return false;
      }
      i++;
    }
    return true;
  }
    
  Description describe(Description description) =>
      description.add('pairwise $_description ').addDescriptionOf(_expected);

  Description describeMismatch(item, Description mismatchDescription,
                               MatchState matchState, bool verbose) {
    if (item is !Iterable) {
      return mismatchDescription.add('not an Iterable');
    } else if (item.length != _expected.length) {
      return mismatchDescription.
          add('length was ${item.length} instead of ${_expected.length}');
    } else {
      return mismatchDescription.
          addDescriptionOf(matchState.state["actual"]).
          add(' not $_description ').
          addDescriptionOf(matchState.state["expected"]).
          add(' at position ${matchState.state["index"]}');
    }
  }
}

