// 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 unittest;

/**
 * Returns a matcher that matches empty strings, maps or collections.
 */
const Matcher isEmpty = const _Empty();

class _Empty extends BaseMatcher {
  const _Empty();
  bool matches(item, MatchState matchState) {
    if (item is Map || item is Collection) {
      return item.isEmpty;
    } else if (item is String) {
      return item.length == 0;
    } else {
      return false;
    }
  }
  Description describe(Description description) =>
      description.add('empty');
}

/** A matcher that matches any null value. */
const Matcher isNull = const _IsNull();

/** A matcher that matches any non-null value. */
const Matcher isNotNull = const _IsNotNull();

class _IsNull extends BaseMatcher {
  const _IsNull();
  bool matches(item, MatchState matchState) => item == null;
  Description describe(Description description) =>
      description.add('null');
}

class _IsNotNull extends BaseMatcher {
  const _IsNotNull();
  bool matches(item, MatchState matchState) => item != null;
  Description describe(Description description) =>
      description.add('not null');
}

/** A matcher that matches the Boolean value true. */
const Matcher isTrue = const _IsTrue();

/** A matcher that matches anything except the Boolean value true. */
const Matcher isFalse = const _IsFalse();

class _IsTrue extends BaseMatcher {
  const _IsTrue();
  bool matches(item, MatchState matchState) => item == true;
  Description describe(Description description) =>
      description.add('true');
}

class _IsFalse extends BaseMatcher {
  const _IsFalse();
  bool matches(item, MatchState matchState) => item != true;
  Description describe(Description description) =>
      description.add('false');
}

/**
 * Returns a matches that matches if the value is the same instance
 * as [object] (`===`).
 */
Matcher same(expected) => new _IsSameAs(expected);

class _IsSameAs extends BaseMatcher {
  final _expected;
  const _IsSameAs(this._expected);
  bool matches(item, MatchState matchState) => item === _expected;
  // If all types were hashable we could show a hash here.
  Description describe(Description description) =>
      description.add('same instance as ').addDescriptionOf(_expected);
}

/**
 * Returns a matcher that does a deep recursive match. This only works
 * with scalars, Maps and Iterables. To handle cyclic structures a
 * recursion depth [limit] can be provided. The default limit is 100.
 */
Matcher equals(expected, [limit=100]) =>
    new _DeepMatcher(expected, limit);

class _DeepMatcher extends BaseMatcher {
  final _expected;
  final int _limit;
  var count;

  _DeepMatcher(this._expected, [limit = 1000]) : this._limit = limit;

  String _compareIterables(expected, actual, matcher, depth) {
    if (actual is !Iterable) {
      return 'is not Iterable';
    }
    var expectedIterator = expected.iterator();
    var actualIterator = actual.iterator();
    var position = 0;
    String reason = null;
    while (reason == null) {
      if (expectedIterator.hasNext) {
        if (actualIterator.hasNext) {
          Description r = matcher(expectedIterator.next(),
                           actualIterator.next(),
                           'mismatch at position ${position}',
                           depth);
          if (r != null) reason = r.toString();
          ++position;
        } else {
          reason = 'shorter than expected';
        }
      } else if (actualIterator.hasNext) {
        reason = 'longer than expected';
      } else {
        return null;
      }
    }
    return reason;
  }

  Description _recursiveMatch(expected, actual, String location, int depth) {
    Description reason = null;
    // If _limit is 1 we can only recurse one level into object.
    bool canRecurse = depth == 0 || _limit > 1;
    if (expected == actual) {
      // Do nothing.
    } else if (depth > _limit) {
      reason = new StringDescription('recursion depth limit exceeded');
    } else {
      if (expected is Iterable && canRecurse) {
        String r = _compareIterables(expected, actual,
          _recursiveMatch, depth+1);
        if (r != null) reason = new StringDescription(r);
      } else if (expected is Map && canRecurse) {
        if (actual is !Map) {
          reason = new StringDescription('expected a map');
        } else if (expected.length != actual.length) {
          reason = new StringDescription('different map lengths');
        } else {
          for (var key in expected.keys) {
            if (!actual.containsKey(key)) {
              reason = new StringDescription('missing map key ');
              reason.addDescriptionOf(key);
              break;
            }
            reason = _recursiveMatch(expected[key], actual[key],
                'with key <${key}> ${location}', depth+1);
            if (reason != null) {
              break;
            }
          }
        }
      } else {
        // If we have recursed, show the expected value too; if not,
        // expect() will show it for us.
        reason = new StringDescription();
        if (depth > 1) {
          reason.add('expected ').addDescriptionOf(expected).add(' but was ').
              addDescriptionOf(actual);
        } else {
          reason.add('was ').addDescriptionOf(actual);
        }
      }
    }
    if (reason != null && location.length > 0) {
      reason.add(' ').add(location);
    }
    return reason;
  }

  String _match(expected, actual) {
    Description reason = _recursiveMatch(expected, actual, '', 0);
    return reason == null ? null : reason.toString();
  }

  // TODO(gram) - see if we can make use of matchState here to avoid
  // recursing again in describeMismatch.
  bool matches(item, MatchState matchState) => _match(_expected, item) == null;

  Description describe(Description description) =>
    description.addDescriptionOf(_expected);

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

/** A matcher that matches any value. */
const Matcher anything = const _IsAnything();

class _IsAnything extends BaseMatcher {
  const _IsAnything();
  bool matches(item, MatchState matchState) => true;
  Description describe(Description description) =>
      description.add('anything');
}

/**
 * Returns a matcher that matches if an object is an instance
 * of [type] (or a subtype).
 *
 * As types are not first class objects in Dart we can only
 * approximate this test by using a generic wrapper class.
 *
 * For example, to test whether 'bar' is an instance of type
 * 'Foo', we would write:
 *
 *     expect(bar, new isInstanceOf<Foo>());
 *
 * To get better error message, supply a name when creating the
 * Type wrapper; e.g.:
 *
 *     expect(bar, new isInstanceOf<Foo>('Foo'));
 *
 * Note that this does not currently work in dart2js; it will
 * match any type, and isNot(new isInstanceof<T>()) will always
 * fail. This is because dart2js currently ignores template type
 * parameters.
 */
class isInstanceOf<T> extends BaseMatcher {
  final String _name;
  const isInstanceOf([name = 'specified type']) : this._name = name;
  bool matches(obj, MatchState matchState) => obj is T;
  // The description here is lame :-(
  Description describe(Description description) =>
      description.add('an instance of ${_name}');
}

/**
 * This can be used to match two kinds of objects:
 *
 *   * A [Function] that throws an exception when called. The function cannot
 *     take any arguments. If you want to test that a function expecting
 *     arguments throws, wrap it in another zero-argument function that calls
 *     the one you want to test.
 *
 *   * A [Future] that completes with an exception. Note that this creates an
 *     asynchronous expectation. The call to `expect()` that includes this will
 *     return immediately and execution will continue. Later, when the future
 *     completes, the actual expectation will run.
 */
const Matcher throws = const Throws();

/**
 * This can be used to match two kinds of objects:
 *
 *   * A [Function] that throws an exception when called. The function cannot
 *     take any arguments. If you want to test that a function expecting
 *     arguments throws, wrap it in another zero-argument function that calls
 *     the one you want to test.
 *
 *   * A [Future] that completes with an exception. Note that this creates an
 *     asynchronous expectation. The call to `expect()` that includes this will
 *     return immediately and execution will continue. Later, when the future
 *     completes, the actual expectation will run.
 *
 * In both cases, when an exception is thrown, this will test that the exception
 * object matches [matcher]. If [matcher] is not an instance of [Matcher], it
 * will implicitly be treated as `equals(matcher)`.
 */
Matcher throwsA(matcher) => new Throws(wrapMatcher(matcher));

/**
 * A matcher that matches a function call against no exception.
 * The function will be called once. Any exceptions will be silently swallowed.
 * The value passed to expect() should be a reference to the function.
 * Note that the function cannot take arguments; to handle this
 * a wrapper will have to be created.
 */
const Matcher returnsNormally = const _ReturnsNormally();

class Throws extends BaseMatcher {
  final Matcher _matcher;

  const Throws([Matcher matcher]) :
    this._matcher = matcher;

  bool matches(item, MatchState matchState) {
    if (item is Future) {
      // Queue up an asynchronous expectation that validates when the future
      // completes.
      item.onComplete(expectAsync1((future) {
        if (future.hasValue) {
          expect(false, isTrue, reason:
              "Expected future to fail, but succeeded with '${future.value}'.");
        } else if (_matcher != null) {
          var reason;
          if (future.stackTrace != null) {
            var stackTrace = future.stackTrace.toString();
            stackTrace = "  ${stackTrace.replaceAll("\n", "\n  ")}";
            reason = "Actual exception trace:\n$stackTrace";
          }
          expect(future.exception, _matcher, reason: reason);
        }
      }));

      // It hasn't failed yet.
      return true;
    }

    try {
      item();
      return false;
    } catch (e, s) {
      if (_matcher == null ||_matcher.matches(e, matchState)) {
        return true;
      } else {
        matchState.state = {
            'exception' :e,
            'stack': s
        };
        return false;
      }
    }
  }

  Description describe(Description description) {
    if (_matcher == null) {
      return description.add("throws an exception");
    } else {
      return description.add('throws an exception which matches ').
          addDescriptionOf(_matcher);
    }
  }

  Description describeMismatch(item, Description mismatchDescription,
                               MatchState matchState,
                               bool verbose) {
    if (_matcher == null ||  matchState.state == null) {
      return mismatchDescription.add(' no exception');
    } else {
      mismatchDescription.
          add(' exception ').addDescriptionOf(matchState.state['exception']);
      if (verbose) {
          mismatchDescription.add(' at ').
          add(matchState.state['stack'].toString());
      }
       mismatchDescription.add(' does not match ').addDescriptionOf(_matcher);
       return mismatchDescription;
    }
  }
}

class _ReturnsNormally extends BaseMatcher {
  const _ReturnsNormally();

  bool matches(f, MatchState matchState) {
    try {
      f();
      return true;
    } catch (e, s) {
      matchState.state = {
          'exception' : e,
          'stack': s
      };
      return false;
    }
  }

  Description describe(Description description) =>
      description.add("return normally");

  Description describeMismatch(item, Description mismatchDescription,
                               MatchState matchState,
                               bool verbose) {
      mismatchDescription.add(' threw ').
          addDescriptionOf(matchState.state['exception']);
      if (verbose) {
        mismatchDescription.add(' at ').
        add(matchState.state['stack'].toString());
      }
      return mismatchDescription;
  }
}

/*
 * Matchers for different exception types. Ideally we should just be able to
 * use something like:
 *
 * final Matcher throwsException =
 *     const _Throws(const isInstanceOf<Exception>());
 *
 * Unfortunately instanceOf is not working with dart2js.
 *
 * Alternatively, if static functions could be used in const expressions,
 * we could use:
 *
 * bool _isException(x) => x is Exception;
 * final Matcher isException = const _Predicate(_isException, "Exception");
 * final Matcher throwsException = const _Throws(isException);
 *
 * But currently using static functions in const expressions is not supported.
 * For now the only solution for all platforms seems to be separate classes
 * for each exception type.
 */

abstract class TypeMatcher extends BaseMatcher {
  final String _name;
  const TypeMatcher(this._name);
  Description describe(Description description) =>
      description.add(_name);
}

/** A matcher for FormatExceptions. */
const isFormatException = const _FormatException();

/** A matcher for functions that throw FormatException. */
const Matcher throwsFormatException =
    const Throws(isFormatException);

class _FormatException extends TypeMatcher {
  const _FormatException() : super("FormatException");
  bool matches(item, MatchState matchState) => item is FormatException;
}

/** A matcher for Exceptions. */
const isException = const _Exception();

/** A matcher for functions that throw Exception. */
const Matcher throwsException = const Throws(isException);

class _Exception extends TypeMatcher {
  const _Exception() : super("Exception");
  bool matches(item, MatchState matchState) => item is Exception;
}

/** A matcher for ArgumentErrors. */
const isArgumentError = const _ArgumentError();

/** A matcher for functions that throw ArgumentError. */
const Matcher throwsArgumentError =
    const Throws(isArgumentError);

class _ArgumentError extends TypeMatcher {
  const _ArgumentError() : super("ArgumentError");
  bool matches(item, MatchState matchState) => item is ArgumentError;
}

/** A matcher for IllegalJSRegExpExceptions. */
const isIllegalJSRegExpException = const _IllegalJSRegExpException();

/** A matcher for functions that throw IllegalJSRegExpException. */
const Matcher throwsIllegalJSRegExpException =
    const Throws(isIllegalJSRegExpException);

class _IllegalJSRegExpException extends TypeMatcher {
  const _IllegalJSRegExpException() : super("IllegalJSRegExpException");
  bool matches(item, MatchState matchState) => item is IllegalJSRegExpException;
}

/** A matcher for RangeErrors. */
const isRangeError = const _RangeError();

/** A matcher for functions that throw RangeError */
const Matcher throwsRangeError =
    const Throws(isRangeError);

class _RangeError extends TypeMatcher {
  const _RangeError() : super("RangeError");
  bool matches(item, MatchState matchState) => item is RangeError;
}

/** A matcher for NoSuchMethodErrors. */
const isNoSuchMethodError = const _NoSuchMethodError();

/** A matcher for functions that throw NoSuchMethodError. */
const Matcher throwsNoSuchMethodError =
    const Throws(isNoSuchMethodError);

class _NoSuchMethodError extends TypeMatcher {
  const _NoSuchMethodError() : super("NoSuchMethodError");
  bool matches(item, MatchState matchState) => item is NoSuchMethodError;
}

/** A matcher for NotImplementedExceptions. */
const isNotImplementedException = const _NotImplementedException();

/** A matcher for functions that throw Exception. */
const Matcher throwsNotImplementedException =
    const Throws(isNotImplementedException);

class _NotImplementedException extends TypeMatcher {
  const _NotImplementedException() : super("NotImplementedException");
  bool matches(item, MatchState matchState) => item is NotImplementedException;
}

/** A matcher for NullPointerExceptions. */
const isNullPointerException = const _NullPointerException();

/** A matcher for functions that throw NotNullPointerException. */
const Matcher throwsNullPointerException =
    const Throws(isNullPointerException);

class _NullPointerException extends TypeMatcher {
  const _NullPointerException() : super("NullPointerException");
  bool matches(item, MatchState matchState) => item is NullPointerException;
}

/** A matcher for UnsupportedError. */
const isUnsupportedError = const _UnsupportedError();

/** A matcher for functions that throw UnsupportedError. */
const Matcher throwsUnsupportedError = const Throws(isUnsupportedError);

class _UnsupportedError extends TypeMatcher {
  const _UnsupportedError() :
      super("UnsupportedError");
  bool matches(item, MatchState matchState) => item is UnsupportedError;
}

/** A matcher for Map types. */
const isMap = const _IsMap();

class _IsMap extends TypeMatcher {
  const _IsMap() : super("Map");
  bool matches(item, MatchState matchState) => item is Map;
}

/** A matcher for List types. */
const isList = const _IsList();

class _IsList extends TypeMatcher {
  const _IsList() : super("List");
  bool matches(item, MatchState matchState) => item is List;
}

/**
 * Returns a matcher that matches if an object has a length property
 * that matches [matcher].
 */
Matcher hasLength(matcher) =>
    new _HasLength(wrapMatcher(matcher));

class _HasLength extends BaseMatcher {
  final Matcher _matcher;
  const _HasLength([Matcher matcher = null]) : this._matcher = matcher;

  bool matches(item, MatchState matchState) {
    return _matcher.matches(item.length, matchState);
  }

  Description describe(Description description) =>
    description.add('an object with length of ').
        addDescriptionOf(_matcher);

  Description describeMismatch(item, Description mismatchDescription,
                               MatchState matchState, bool verbose) {
    super.describeMismatch(item, mismatchDescription, matchState, verbose);
    try {
      // We want to generate a different description if there is no length
      // property. This is harmless code that will throw if no length property
      // but subtle enough that an optimizer shouldn't strip it out.
      if (item.length * item.length >= 0) {
        return mismatchDescription.add(' with length of ').
            addDescriptionOf(item.length);
      }
    } catch (e) {
      return mismatchDescription.add(' has no length property');
    }
  }
}

/**
 * Returns a matcher that matches if the match argument contains
 * the expected value. For [String]s this means substring matching;
 * for [Map]s is means the map has the key, and for [Collection]s it
 * means the collection has a matching element. In the case of collections,
 * [expected] can itself be a matcher.
 */
Matcher contains(expected) => new _Contains(expected);

class _Contains extends BaseMatcher {

  final _expected;

  const _Contains(this._expected);

  bool matches(item, MatchState matchState) {
    if (item is String) {
      return item.indexOf(_expected) >= 0;
    } else if (item is Collection) {
      if (_expected is Matcher) {
        return item.some((e) => _expected.matches(e, matchState));
      } else {
        return item.some((e) => e == _expected);
      }
    } else if (item is Map) {
      return item.containsKey(_expected);
    }
    return false;
  }

  Description describe(Description description) =>
      description.add('contains ').addDescriptionOf(_expected);
}

/**
 * Returns a matcher that matches if the match argument is in
 * the expected value. This is the converse of [contains].
 */
Matcher isIn(expected) => new _In(expected);

class _In extends BaseMatcher {

  final _expected;

  const _In(this._expected);

  bool matches(item, MatchState matchState) {
    if (_expected is String) {
      return _expected.indexOf(item) >= 0;
    } else if (_expected is Collection) {
      return _expected.some((e) => e == item);
    } else if (_expected is Map) {
      return _expected.containsKey(item);
    }
    return false;
  }

  Description describe(Description description) =>
      description.add('is in ').addDescriptionOf(_expected);
}

/**
 * Returns a matcher that uses an arbitrary function that returns
 * true or false for the actual value.
 */
Matcher predicate(f, [description ='satisfies function']) =>
    new _Predicate(f, description);

class _Predicate extends BaseMatcher {

  final _matcher;
  final String _description;

  const _Predicate(this._matcher, this._description);

  bool matches(item, MatchState matchState) => _matcher(item);

  Description describe(Description description) =>
      description.add(_description);
}

/**
 * A useful utility class for implementing other matchers through inheritance.
 * Derived classes should call the base constructor with a feature name and
 * description, and an instance matcher, and should implement the
 * [featureValueOf] abstract method.
 *
 * The feature description will typically describe the item and the feature,
 * while the feature name will just name the feature. For example, we may
 * have a Widget class where each Widget has a price; we could make a
 * FeatureMatcher that can make assertions about prices with:
 *
 *     class HasPrice extends FeatureMatcher {
 *       const HasPrice(matcher) :
 *           super("Widget with price that is", "price", matcher);
 *       featureValueOf(actual) => actual.price;
 *     }
 *
 * and then use this for example like:
 *
 *      expect(inventoryItem, new HasPrice(greaterThan(0)));
 */
class CustomMatcher extends BaseMatcher {
  final String _featureDescription;
  final String _featureName;
  final Matcher _matcher;

  const CustomMatcher(this._featureDescription, this._featureName,
      this._matcher);

  /** Override this to extract the interesting feature.*/
  featureValueOf(actual) => actual;

  bool matches(item, MatchState matchState) {
    var f = featureValueOf(item);
    if (_matcher.matches(f, matchState)) return true;
    matchState.state = { 'innerState': matchState.state, 'feature': f };
    return false;
  }

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

  Description describeMismatch(item, Description mismatchDescription,
                               MatchState matchState, bool verbose) {
    mismatchDescription.add(_featureName).add(' ');
    _matcher.describeMismatch(matchState.state['feature'], mismatchDescription,
        matchState.state['innerState'], verbose);
    return mismatchDescription;
  }
}
