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

/** The objects thrown by the default failure handler. */
class TestFailure extends Error {
  final String message;

  TestFailure(this.message);

  String toString() => message;
}

/**
 * Useful utility for nesting match states.
 */

void addStateInfo(Map matchState, Map values) {
  var innerState = new Map.from(matchState);
  matchState.clear();
  matchState['state'] = innerState;
  matchState.addAll(values);
}

/**
 * Some matchers, like those for Futures and exception testing,
 * can fail in asynchronous sections, and throw exceptions.
 * A user of this library will typically want to catch and handle
 * such exceptions. The [wrapAsync] property is a function that
 * can wrap callbacks used by these Matchers so that they can be
 * used safely. For example, the unittest library will set this
 * to be `expectAsync`. By default this is an identity function.
 */
Function wrapAsync = (Function f, [id]) => f;

/**
 * This is the main assertion function. It asserts that [actual]
 * matches the [matcher]. [reason] is optional and is typically not
 * supplied, as a reason is generated from the matcher; if [reason]
 * is included it is appended to the reason generated by the matcher.
 *
 * [matcher] can be a value in which case it will be wrapped in an
 * [equals] matcher.
 *
 * If the assertion fails, then the default behavior is to throw a
 * [TestFailure], but this behavior can be changed by calling
 * [configureExpectFailureHandler] and providing an alternative handler that
 * implements the [IFailureHandler] interface. It is also possible to
 * pass a [failureHandler] to [expect] as a final parameter for fine-
 * grained control.
 *
 * In some cases extra diagnostic info can be produced on failure (for
 * example, stack traces on mismatched exceptions). To enable these,
 * [verbose] should be specified as true;
 */
void expect(actual, matcher, {String reason, FailureHandler failureHandler,
            bool verbose : false}) {
  matcher = wrapMatcher(matcher);
  bool doesMatch;
  var matchState = {};
  try {
    doesMatch = matcher.matches(actual, matchState);
  } catch (e, trace) {
    doesMatch = false;
    if (reason == null) {
      reason = '${(e is String) ? e : e.toString()} at $trace';
    }
  }
  if (!doesMatch) {
    if (failureHandler == null) {
      failureHandler = getOrCreateExpectFailureHandler();
    }
    failureHandler.failMatch(actual, matcher, reason, matchState, verbose);
  }
}

void fail(String message, {FailureHandler failureHandler}) {
  if (failureHandler == null) {
    failureHandler = getOrCreateExpectFailureHandler();
  }
  failureHandler.fail(message);
}

/**
 * Takes an argument and returns an equivalent matcher.
 * If the argument is already a matcher this does nothing,
 * else if the argument is a function, it generates a predicate
 * function matcher, else it generates an equals matcher.
 */
Matcher wrapMatcher(x) {
  if (x is Matcher) {
    return x;
  } else if (x is Function) {
    return predicate(x);
  } else {
    return equals(x);
  }
}

// The handler for failed asserts.
FailureHandler _assertFailureHandler = null;

// The default failure handler that throws [TestFailure]s.
class DefaultFailureHandler implements FailureHandler {
  DefaultFailureHandler() {
    if (_assertErrorFormatter == null) {
      _assertErrorFormatter = _defaultErrorFormatter;
    }
  }
  void fail(String reason) {
    throw new TestFailure(reason);
  }
  void failMatch(actual, Matcher matcher, String reason,
      Map matchState, bool verbose) {
    fail(_assertErrorFormatter(actual, matcher, reason, matchState, verbose));
  }
}

/**
 * Changes or resets to the default the failure handler for expect()
 * [handler] is a reference to the new handler; if this is omitted
 * or null then the failure handler is reset to the default, which
 * throws [TestFailure]s on [expect] assertion failures.
 */
void configureExpectFailureHandler([FailureHandler handler = null]) {
  if (handler == null) {
    handler = new DefaultFailureHandler();
  }
  _assertFailureHandler = handler;
}

FailureHandler getOrCreateExpectFailureHandler() {
  if (_assertFailureHandler == null) {
    configureExpectFailureHandler();
  }
  return _assertFailureHandler;
}

// The error message formatter for failed asserts.
ErrorFormatter _assertErrorFormatter = null;

// The default error formatter implementation.
String _defaultErrorFormatter(actual, Matcher matcher, String reason,
    Map matchState, bool verbose) {
  var description = new StringDescription();
  description.add('Expected: ').addDescriptionOf(matcher).add('\n');
  description.add('  Actual: ').addDescriptionOf(actual).add('\n');

  var mismatchDescription = new StringDescription();
  matcher.describeMismatch(actual, mismatchDescription, matchState, verbose);

  if (mismatchDescription.length > 0) {
    description.add('   Which: ${mismatchDescription}\n');
  }
  if (reason != null) {
    description.add(reason).add('\n');
  }
  return description.toString();
}

/**
 * Changes or resets to default the failure message formatter for expect().
 * [formatter] is a reference to the new formatter; if this is omitted or
 * null then the failure formatter is reset to the default. The new
 * formatter is returned; this allows custom expect handlers to easily
 * get a reference to the default formatter.
 */
ErrorFormatter configureExpectFormatter([ErrorFormatter formatter = null]) {
  if (formatter == null) {
    formatter = _defaultErrorFormatter;
  }
  return _assertErrorFormatter = formatter;
}

