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

library matcher.expect;

import 'core_matchers.dart';
import 'description.dart';
import 'interfaces.dart';

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