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

/**
 * A simple mocking/spy library.
 *
 * ## Installing ##
 *
 * Use [pub][] to install this package. Add the following to your `pubspec.yaml`
 * file.
 *
 *     dependencies:
 *       mock: any
 *
 * Then run `pub install`.
 *
 * For more information, see the
 * [mock package on pub.dartlang.org](http://pub.dartlang.org/packages/mock).
 *
 * ## Using ##
 *
 * To create a mock objects for some class T, create a new class using:
 *
 *     class MockT extends Mock implements T {};
 *
 * Then specify the [Behavior] of the Mock for different methods using
 * [when] (to select the method and parameters) and then the [Action]s
 * for the [Behavior] by calling [thenReturn], [alwaysReturn], [thenThrow],
 * [alwaysThrow], [thenCall] or [alwaysCall].
 *
 * [thenReturn], [thenThrow] and [thenCall] are one-shot so you would
 * typically call these more than once to specify a sequence of actions;
 * this can be done with chained calls, e.g.:
 *
 *      m.when(callsTo('foo')).
 *          thenReturn(0).thenReturn(1).thenReturn(2);
 *
 * [thenCall] and [alwaysCall] allow you to proxy mocked methods, chaining
 * to some other implementation. This provides a way to implement 'spies'.
 *
 * For getters and setters, use "get foo" and "set foo"-style arguments
 * to [callsTo].
 *
 * You can disable logging for a particular [Behavior] easily:
 *
 *     m.when(callsTo('bar')).logging = false;
 *
 * You can then use the mock object. Once you are done, to verify the
 * behavior, use [getLogs] to extract a relevant subset of method call
 * logs and apply [Matchers] to these through calling [verify].
 *
 * A Mock can be given a name when constructed. In this case instead of
 * keeping its own log, it uses a shared log. This can be useful to get an
 * audit trail of interleaved behavior. It is the responsibility of the user
 * to ensure that mock names, if used, are unique.
 *
 * Limitations:
 *
 * * only positional parameters are supported (up to 10);
 * * to mock getters you will need to include parentheses in the call
 *       (e.g. m.length() will work but not m.length).
 *
 * Here is a simple example:
 *
 *     class MockList extends Mock implements List {};
 *
 *     List m = new MockList();
 *     m.when(callsTo('add', anything)).alwaysReturn(0);
 *
 *     m.add('foo');
 *     m.add('bar');
 *
 *     getLogs(m, callsTo('add', anything)).verify(happenedExactly(2));
 *     getLogs(m, callsTo('add', 'foo')).verify(happenedOnce);
 *     getLogs(m, callsTo('add', 'isNull)).verify(neverHappened);
 *
 * Note that we don't need to provide argument matchers for all arguments,
 * but we do need to provide arguments for all matchers. So this is allowed:
 *
 *     m.when(callsTo('add')).alwaysReturn(0);
 *     m.add(1, 2);
 *
 * But this is not allowed and will throw an exception:
 *
 *     m.when(callsTo('add', anything, anything)).alwaysReturn(0);
 *     m.add(1);
 *
 * Here is a way to implement a 'spy', which is where we log the call
 * but then hand it off to some other function, which is the same
 * method in a real instance of the class being mocked:
 *
 *     class Foo {
 *       bar(a, b, c) => a + b + c;
 *     }
 *
 *     class MockFoo extends Mock implements Foo {
 *       Foo real;
 *       MockFoo() {
 *         real = new Foo();
 *         this.when(callsTo('bar')).alwaysCall(real.bar);
 *       }
 *     }
 *
 * [pub]: http://pub.dartlang.org
 */

library mock;

import 'dart:mirrors' show MirrorSystem;

import 'matcher.dart';

/**
 * The error formatter for mocking is a bit different from the default one
 * for unit testing; instead of the third argument being a 'reason'
 * it is instead a [signature] describing the method signature filter
 * that was used to select the logs that were verified.
 */
String _mockingErrorFormatter(actual, Matcher matcher, String signature,
                              MatchState matchState, bool verbose) {
  var description = new StringDescription();
  description.add('Expected ${signature} ').addDescriptionOf(matcher).
      add('\n     but: ');
  matcher.describeMismatch(actual, description, matchState, verbose).add('.');
  return description.toString();
}

/**
 * The failure handler for the [expect()] calls that occur in [verify()]
 * methods in the mock objects. This calls the real failure handler used
 * by the unit test library after formatting the error message with
 * the custom formatter.
 */
class _MockFailureHandler implements FailureHandler {
  FailureHandler proxy;
  _MockFailureHandler(this.proxy);
  void fail(String reason) {
    proxy.fail(reason);
  }
  void failMatch(actual, Matcher matcher, String reason,
                 MatchState matchState, bool verbose) {
    proxy.fail(_mockingErrorFormatter(actual, matcher, reason,
        matchState, verbose));
  }
}

_MockFailureHandler _mockFailureHandler = null;

/** Sentinel value for representing no argument. */
class _Sentinel {
  const _Sentinel();
}
const _noArg = const _Sentinel();

/** The ways in which a call to a mock method can be handled. */
class Action {
  /** Do nothing (void method) */
  static const IGNORE = const Action._('IGNORE');

  /** Return a supplied value. */
  static const RETURN = const Action._('RETURN');

  /** Throw a supplied value. */
  static const THROW = const Action._('THROW');

  /** Call a supplied function. */
  static const PROXY = const Action._('PROXY');

  const Action._(this.name);

  final String name;
}

/**
 * The behavior of a method call in the mock library is specified
 * with [Responder]s. A [Responder] has a [value] to throw
 * or return (depending on the type of [action]),
 * and can either be one-shot, multi-shot, or infinitely repeating,
 * depending on the value of [count (1, greater than 1, or 0 respectively).
 */
class Responder {
  var value;
  Action action;
  int count;
  Responder(this.value, [this.count = 1, this.action = Action.RETURN]);
}

/**
 * A [CallMatcher] is a special matcher used to match method calls (i.e.
 * a method name and set of arguments). It is not a [Matcher] like the
 * unit test [Matcher], but instead represents a method name and a
 * collection of [Matcher]s, one per argument, that will be applied
 * to the parameters to decide if the method call is a match.
 */
class CallMatcher {
  Matcher nameFilter;
  List<Matcher> argMatchers;

  /**
   * Constructor for [CallMatcher]. [name] can be null to
   * match anything, or a literal [String], a predicate [Function],
   * or a [Matcher]. The various arguments can be scalar values or
   * [Matcher]s.
   */
  CallMatcher([name,
              arg0 = _noArg,
              arg1 = _noArg,
              arg2 = _noArg,
              arg3 = _noArg,
              arg4 = _noArg,
              arg5 = _noArg,
              arg6 = _noArg,
              arg7 = _noArg,
              arg8 = _noArg,
              arg9 = _noArg]) {
    if (name == null) {
      nameFilter = anything;
    } else {
      nameFilter = wrapMatcher(name);
    }
    argMatchers = new List<Matcher>();
    if (identical(arg0, _noArg)) return;
    argMatchers.add(wrapMatcher(arg0));
    if (identical(arg1, _noArg)) return;
    argMatchers.add(wrapMatcher(arg1));
    if (identical(arg2, _noArg)) return;
    argMatchers.add(wrapMatcher(arg2));
    if (identical(arg3, _noArg)) return;
    argMatchers.add(wrapMatcher(arg3));
    if (identical(arg4, _noArg)) return;
    argMatchers.add(wrapMatcher(arg4));
    if (identical(arg5, _noArg)) return;
    argMatchers.add(wrapMatcher(arg5));
    if (identical(arg6, _noArg)) return;
    argMatchers.add(wrapMatcher(arg6));
    if (identical(arg7, _noArg)) return;
    argMatchers.add(wrapMatcher(arg7));
    if (identical(arg8, _noArg)) return;
    argMatchers.add(wrapMatcher(arg8));
    if (identical(arg9, _noArg)) return;
    argMatchers.add(wrapMatcher(arg9));
  }

  /**
   * We keep our behavior specifications in a Map, which is keyed
   * by the [CallMatcher]. To make the keys unique and to get a
   * descriptive value for the [CallMatcher] we have this override
   * of [toString()].
   */
  String toString() {
    Description d = new StringDescription();
    d.addDescriptionOf(nameFilter);
    // If the nameFilter was a simple string - i.e. just a method name -
    // strip the quotes to make this more natural in appearance.
    if (d.toString()[0] == "'") {
      d.replace(d.toString().substring(1, d.toString().length - 1));
    }
    d.add('(');
    for (var i = 0; i < argMatchers.length; i++) {
      if (i > 0) d.add(', ');
      d.addDescriptionOf(argMatchers[i]);
    }
    d.add(')');
    return d.toString();
  }

  /**
   * Given a [method] name and list of [arguments], return true
   * if it matches this [CallMatcher.
   */
  bool matches(String method, List arguments) {
    var matchState = new MatchState();
    if (!nameFilter.matches(method, matchState)) {
      return false;
    }
    var numArgs = (arguments == null) ? 0 : arguments.length;
    if (numArgs < argMatchers.length) {
      throw new Exception("Less arguments than matchers for $method.");
    }
    for (var i = 0; i < argMatchers.length; i++) {
      if (!argMatchers[i].matches(arguments[i], matchState)) {
        return false;
      }
    }
    return true;
  }
}

/**
 * Returns a [CallMatcher] for the specified signature. [method] can be
 * null to match anything, or a literal [String], a predicate [Function],
 * or a [Matcher]. The various arguments can be scalar values or [Matcher]s.
 * To match getters and setters, use "get " and "set " prefixes on the names.
 * For example, for a property "foo", you could use "get foo" and "set foo"
 * as literal string arguments to callsTo to match the getter and setter
 * of "foo".
 */
CallMatcher callsTo([method,
                     arg0 = _noArg,
                     arg1 = _noArg,
                     arg2 = _noArg,
                     arg3 = _noArg,
                     arg4 = _noArg,
                     arg5 = _noArg,
                     arg6 = _noArg,
                     arg7 = _noArg,
                     arg8 = _noArg,
                     arg9 = _noArg]) {
  return new CallMatcher(method, arg0, arg1, arg2, arg3, arg4,
      arg5, arg6, arg7, arg8, arg9);
}

/**
 * A [Behavior] represents how a [Mock] will respond to one particular
 * type of method call.
 */
class Behavior {
  CallMatcher matcher; // The method call matcher.
  List<Responder> actions; // The values to return/throw or proxies to call.
  bool logging = true;

  Behavior (this.matcher) {
    actions = new List<Responder>();
  }

  /**
   * Adds a [Responder] that returns a [value] for [count] calls
   * (1 by default).
   */
  Behavior thenReturn(value, [count = 1]) {
    actions.add(new Responder(value, count, Action.RETURN));
    return this; // For chaining calls.
  }

  /** Adds a [Responder] that repeatedly returns a [value]. */
  Behavior alwaysReturn(value) {
    return thenReturn(value, 0);
  }

  /**
   * Adds a [Responder] that throws [value] [count]
   * times (1 by default).
   */
  Behavior thenThrow(value, [count = 1]) {
    actions.add(new Responder(value, count, Action.THROW));
    return this; // For chaining calls.
  }

  /** Adds a [Responder] that throws [value] endlessly. */
  Behavior alwaysThrow(value) {
    return thenThrow(value, 0);
  }

  /**
   * [thenCall] creates a proxy Responder, that is called [count]
   * times (1 by default; 0 is used for unlimited calls, and is
   * exposed as [alwaysCall]). [value] is the function that will
   * be called with the same arguments that were passed to the
   * mock. Proxies can be used to wrap real objects or to define
   * more complex return/throw behavior. You could even (if you
   * wanted) use proxies to emulate the behavior of thenReturn;
   * e.g.:
   *
   *     m.when(callsTo('foo')).thenReturn(0)
   *
   * is equivalent to:
   *
   *     m.when(callsTo('foo')).thenCall(() => 0)
   */
  Behavior thenCall(value, [count = 1]) {
    actions.add(new Responder(value, count, Action.PROXY));
    return this; // For chaining calls.
  }

  /** Creates a repeating proxy call. */
  Behavior alwaysCall(value) {
    return thenCall(value, 0);
  }

  /** Returns true if a method call matches the [Behavior]. */
  bool matches(String method, List args) => matcher.matches(method, args);

  /** Returns the [matcher]'s representation. */
  String toString() => matcher.toString();
}

/**
 * Every call to a [Mock] object method is logged. The logs are
 * kept in instances of [LogEntry].
 */
class LogEntry {
  /** The time of the event. */
  DateTime time;

  /** The mock object name, if any. */
  final String mockName;

  /** The method name. */
  final String methodName;

  /** The parameters. */
  final List args;

  /** The behavior that resulted. */
  final Action action;

  /** The value that was returned (if no throw). */
  final value;

  LogEntry(this.mockName, this.methodName,
      this.args, this.action, [this.value]) {
    time = new DateTime.now();
  }

  String _pad2(int val) => (val >= 10 ? '$val' : '0$val');

  String toString([DateTime baseTime]) {
    Description d = new StringDescription();
    if (baseTime == null) {
      // Show absolute time.
      d.add('${time.hour}:${_pad2(time.minute)}:'
          '${_pad2(time.second)}.${time.millisecond}>  ');
    } else {
      // Show relative time.
      int delta = time.millisecondsSinceEpoch - baseTime.millisecondsSinceEpoch;
      int secs = delta ~/ 1000;
      int msecs = delta % 1000;
      d.add('$secs.$msecs>  ');
    }
    d.add('${_qualifiedName(mockName, methodName)}(');
    if (args != null) {
      for (var i = 0; i < args.length; i++) {
        if (i != 0) d.add(', ');
        d.addDescriptionOf(args[i]);
      }
    }
    d.add(') ${action == Action.THROW ? "threw" : "returned"} ');
    d.addDescriptionOf(value);
    return d.toString();
  }
}

/** Utility function for optionally qualified method names */
String _qualifiedName(owner, String method) {
  if (owner == null || identical(owner, anything)) {
    return method;
  } else if (owner is Matcher) {
    Description d = new StringDescription();
    d.addDescriptionOf(owner);
    d.add('.');
    d.add(method);
    return d.toString();
  } else {
    return '$owner.$method';
  }
}

/**
* [StepValidator]s are used by [stepwiseValidate] in [LogEntryList], which
* iterates through the list and call the [StepValidator] function with the
* log [List] and position. The [StepValidator] should return the number of
* positions to advance upon success, or zero upon failure. When zero is
* returned an error is reported.
*/
typedef int StepValidator(List<LogEntry> logs, int pos);

/**
 * We do verification on a list of [LogEntry]s. To allow chaining
 * of calls to verify, we encapsulate such a list in the [LogEntryList]
 * class.
 */
class LogEntryList {
  String filter;
  List<LogEntry> logs;
  LogEntryList([this.filter]) {
    logs = new List<LogEntry>();
  }

  /** Add a [LogEntry] to the log. */
  add(LogEntry entry) => logs.add(entry);

  /** Get the first entry, or null if no entries. */
  get first => (logs == null || logs.length == 0) ? null : logs[0];

  /** Get the last entry, or null if no entries. */
  get last => (logs == null || logs.length == 0) ? null : logs.last;

  /** Creates a LogEntry predicate function from the argument. */
  Function _makePredicate(arg) {
    if (arg == null) {
      return (e) => true;
    } else if (arg is CallMatcher) {
      return (e) => arg.matches(e.methodName, e.args);
    } else if (arg is Function) {
      return arg;
    } else {
      throw new Exception("Invalid argument to _makePredicate.");
    }
  }

  /**
   * Create a new [LogEntryList] consisting of [LogEntry]s from
   * this list that match the specified [mockNameFilter] and [logFilter].
   * [mockNameFilter] can be null, a [String], a predicate [Function],
   * or a [Matcher]. If [mockNameFilter] is null, this is the same as
   * [anything].
   * If [logFilter] is null, all entries in the log will be returned.
   * Otherwise [logFilter] should be a [CallMatcher] or  predicate function
   * that takes a [LogEntry] and returns a bool.
   * If [destructive] is true, the log entries are removed from the
   * original list.
   */
  LogEntryList getMatches([mockNameFilter,
                          logFilter,
                          Matcher actionMatcher,
                          bool destructive = false]) {
    if (mockNameFilter == null) {
      mockNameFilter = anything;
    } else {
      mockNameFilter = wrapMatcher(mockNameFilter);
    }
    Function entryFilter = _makePredicate(logFilter);
    String filterName = _qualifiedName(mockNameFilter, logFilter.toString());
    LogEntryList rtn = new LogEntryList(filterName);
    MatchState matchState = new MatchState();
    for (var i = 0; i < logs.length; i++) {
      LogEntry entry = logs[i];
      if (mockNameFilter.matches(entry.mockName, matchState) &&
          entryFilter(entry)) {
        if (actionMatcher == null ||
            actionMatcher.matches(entry, matchState)) {
          rtn.add(entry);
          if (destructive) {
            int startIndex = i--;
            logs.removeRange(startIndex, startIndex + 1);
          }
        }
      }
    }
    return rtn;
  }

  /** Apply a unit test [Matcher] to the [LogEntryList]. */
  LogEntryList verify(Matcher matcher) {
    if (_mockFailureHandler == null) {
      _mockFailureHandler =
          new _MockFailureHandler(getOrCreateExpectFailureHandler());
    }
    expect(logs, matcher, reason:filter, failureHandler: _mockFailureHandler);
    return this;
  }

  /**
   * Iterate through the list and call the [validator] function with the
   * log [List] and position. The [validator] should return the number of
   * positions to advance upon success, or zero upon failure. When zero is
   * returned an error is reported. [reason] can be used to provide a
   * more descriptive failure message. If a failure occurred false will be
   * returned (unless the failure handler itself threw an exception);
   * otherwise true is returned.
   * The use case here is to perform more complex validations; for example
   * we may want to assert that the return value from some function is
   * later used as a parameter to a following function. If we filter the logs
   * to include just these two functions we can write a simple validator to
   * do this check.
   */
  bool stepwiseValidate(StepValidator validator, [String reason = '']) {
    if (_mockFailureHandler == null) {
      _mockFailureHandler =
          new _MockFailureHandler(getOrCreateExpectFailureHandler());
    }
    var i = 0;
    while (i < logs.length) {
      var n = validator(logs, i);
      if (n == 0) {
        if (reason.length > 0) {
          reason = ': $reason';
        }
        _mockFailureHandler.fail("Stepwise validation failed at $filter "
                                 "position $i$reason");
        return false;
      } else {
        i += n;
      }
    }
    return true;
  }

  /**
   * Turn the logs into human-readable text. If [baseTime] is specified
   * then each entry is prefixed with the offset from that time in
   * milliseconds; otherwise the time of day is used.
   */
  String toString([DateTime baseTime]) {
    String s = '';
    for (var e in logs) {
      s = '$s${e.toString(baseTime)}\n';
    }
    return s;
  }

  /**
   *  Find the first log entry that satisfies [logFilter] and
   *  return its position. A search [start] position can be provided
   *  to allow for repeated searches. [logFilter] can be a [CallMatcher],
   *  or a predicate function that takes a [LogEntry] argument and returns
   *  a bool. If [logFilter] is null, it will match any [LogEntry].
   *  If no entry is found, then [failureReturnValue] is returned.
   *  After each check the position is updated by [skip], so using
   *  [skip] of -1 allows backward searches, using a [skip] of 2 can
   *  be used to check pairs of adjacent entries, and so on.
   */
  int findLogEntry(logFilter, [int start = 0, int failureReturnValue = -1,
      skip = 1]) {
    logFilter = _makePredicate(logFilter);
    int pos = start;
    while (pos >= 0 && pos < logs.length) {
      if (logFilter(logs[pos])) {
        return pos;
      }
      pos += skip;
    }
    return failureReturnValue;
  }

  /**
   * Returns log events that happened up to the first one that
   * satisfies [logFilter]. If [inPlace] is true, then returns
   * this LogEntryList after removing the from the first satisfier;
   * onwards otherwise a new list is created. [description]
   * is used to create a new name for the resulting list.
   * [defaultPosition] is used as the index of the matching item in
   * the case that no match is found.
   */
  LogEntryList _head(logFilter, bool inPlace,
                     String description, int defaultPosition) {
    if (filter != null) {
      description = '$filter $description';
    }
    int pos = findLogEntry(logFilter, 0, defaultPosition);
    if (inPlace) {
      if (pos < logs.length) {
        logs.removeRange(pos, logs.length);
      }
      filter = description;
      return this;
    } else {
      LogEntryList newList = new LogEntryList(description);
      for (var i = 0; i < pos; i++) {
        newList.logs.add(logs[i]);
      }
      return newList;
    }
  }

  /**
   * Returns log events that happened from the first one that
   * satisfies [logFilter]. If [inPlace] is true, then returns
   * this LogEntryList after removing the entries up to the first
   * satisfier; otherwise a new list is created. [description]
   * is used to create a new name for the resulting list.
   * [defaultPosition] is used as the index of the matching item in
   * the case that no match is found.
   */
  LogEntryList _tail(logFilter, bool inPlace,
                     String description, int defaultPosition) {
    if (filter != null) {
      description = '$filter $description';
    }
    int pos = findLogEntry(logFilter, 0, defaultPosition);
    if (inPlace) {
      if (pos > 0) {
        logs.removeRange(0, pos);
      }
      filter = description;
      return this;
    } else {
      LogEntryList newList = new LogEntryList(description);
      while (pos < logs.length) {
        newList.logs.add(logs[pos++]);
      }
      return newList;
    }
  }

  /**
   * Returns log events that happened after [when]. If [inPlace]
   * is true, then it returns this LogEntryList after removing
   * the entries that happened up to [when]; otherwise a new
   * list is created.
   */
  LogEntryList after(DateTime when, [bool inPlace = false]) =>
      _tail((e) => e.time.isAfter(when), inPlace, 'after $when', logs.length);

  /**
   * Returns log events that happened from [when] onwards. If
   * [inPlace] is true, then it returns this LogEntryList after
   * removing the entries that happened before [when]; otherwise
   * a new list is created.
   */
  LogEntryList from(DateTime when, [bool inPlace = false]) =>
      _tail((e) => !e.time.isBefore(when), inPlace, 'from $when', logs.length);

  /**
   * Returns log events that happened until [when]. If [inPlace]
   * is true, then it returns this LogEntryList after removing
   * the entries that happened after [when]; otherwise a new
   * list is created.
   */
  LogEntryList until(DateTime when, [bool inPlace = false]) =>
      _head((e) => e.time.isAfter(when), inPlace, 'until $when', logs.length);

  /**
   * Returns log events that happened before [when]. If [inPlace]
   * is true, then it returns this LogEntryList after removing
   * the entries that happened from [when] onwards; otherwise a new
   * list is created.
   */
  LogEntryList before(DateTime when, [bool inPlace = false]) =>
      _head((e) => !e.time.isBefore(when),
            inPlace,
            'before $when',
            logs.length);

  /**
   * Returns log events that happened after [logEntry]'s time.
   * If [inPlace] is true, then it returns this LogEntryList after
   * removing the entries that happened up to [when]; otherwise a new
   * list is created. If [logEntry] is null the current time is used.
   */
  LogEntryList afterEntry(LogEntry logEntry, [bool inPlace = false]) =>
      after(logEntry == null ? new DateTime.now() : logEntry.time);

  /**
   * Returns log events that happened from [logEntry]'s time onwards.
   * If [inPlace] is true, then it returns this LogEntryList after
   * removing the entries that happened before [when]; otherwise
   * a new list is created. If [logEntry] is null the current time is used.
   */
  LogEntryList fromEntry(LogEntry logEntry, [bool inPlace = false]) =>
      from(logEntry == null ? new DateTime.now() : logEntry.time);

  /**
   * Returns log events that happened until [logEntry]'s time. If
   * [inPlace] is true, then it returns this LogEntryList after removing
   * the entries that happened after [when]; otherwise a new
   * list is created. If [logEntry] is null the epoch time is used.
   */
  LogEntryList untilEntry(LogEntry logEntry, [bool inPlace = false]) =>
      until(logEntry == null ?
          new DateTime.fromMillisecondsSinceEpoch(0) : logEntry.time);

  /**
   * Returns log events that happened before [logEntry]'s time. If
   * [inPlace] is true, then it returns this LogEntryList after removing
   * the entries that happened from [when] onwards; otherwise a new
   * list is created. If [logEntry] is null the epoch time is used.
   */
  LogEntryList beforeEntry(LogEntry logEntry, [bool inPlace = false]) =>
      before(logEntry == null ?
          new DateTime.fromMillisecondsSinceEpoch(0) : logEntry.time);

  /**
   * Returns log events that happened after the first event in [segment].
   * If [inPlace] is true, then it returns this LogEntryList after removing
   * the entries that happened earlier; otherwise a new list is created.
   */
  LogEntryList afterFirst(LogEntryList segment, [bool inPlace = false]) =>
      afterEntry(segment.first, inPlace);

  /**
   * Returns log events that happened after the last event in [segment].
   * If [inPlace] is true, then it returns this LogEntryList after removing
   * the entries that happened earlier; otherwise a new list is created.
   */
  LogEntryList afterLast(LogEntryList segment, [bool inPlace = false]) =>
      afterEntry(segment.last, inPlace);

  /**
   * Returns log events that happened from the time of the first event in
   * [segment] onwards. If [inPlace] is true, then it returns this
   * LogEntryList after removing the earlier entries; otherwise a new list
   * is created.
   */
  LogEntryList fromFirst(LogEntryList segment, [bool inPlace = false]) =>
      fromEntry(segment.first, inPlace);

  /**
   * Returns log events that happened from the time of the last event in
   * [segment] onwards. If [inPlace] is true, then it returns this
   * LogEntryList after removing the earlier entries; otherwise a new list
   * is created.
   */
  LogEntryList fromLast(LogEntryList segment, [bool inPlace = false]) =>
      fromEntry(segment.last, inPlace);

  /**
   * Returns log events that happened until the first event in [segment].
   * If [inPlace] is true, then it returns this LogEntryList after removing
   * the entries that happened later; otherwise a new list is created.
   */
  LogEntryList untilFirst(LogEntryList segment, [bool inPlace = false]) =>
      untilEntry(segment.first, inPlace);

  /**
   * Returns log events that happened until the last event in [segment].
   * If [inPlace] is true, then it returns this LogEntryList after removing
   * the entries that happened later; otherwise a new list is created.
   */
  LogEntryList untilLast(LogEntryList segment, [bool inPlace = false]) =>
      untilEntry(segment.last, inPlace);

  /**
   * Returns log events that happened before the first event in [segment].
   * If [inPlace] is true, then it returns this LogEntryList after removing
   * the entries that happened later; otherwise a new list is created.
   */
  LogEntryList beforeFirst(LogEntryList segment, [bool inPlace = false]) =>
      beforeEntry(segment.first, inPlace);

  /**
   * Returns log events that happened before the last event in [segment].
   * If [inPlace] is true, then it returns this LogEntryList after removing
   * the entries that happened later; otherwise a new list is created.
   */
  LogEntryList beforeLast(LogEntryList segment, [bool inPlace = false]) =>
      beforeEntry(segment.last, inPlace);

  /**
   * Iterate through the LogEntryList looking for matches to the entries
   * in [keys]; for each match found the closest [distance] neighboring log
   * entries that match [mockNameFilter] and [logFilter] will be included in
   * the result. If [isPreceding] is true we use the neighbors that precede
   * the matched entry; else we use the neighbors that followed.
   * If [includeKeys] is true then the entries in [keys] that resulted in
   * entries in the output list are themselves included in the output list. If
   * [distance] is zero then all matches are included.
   */
  LogEntryList _neighboring(bool isPreceding,
                            LogEntryList keys,
                            mockNameFilter,
                            logFilter,
                            int distance,
                            bool includeKeys) {
    String filterName = 'Calls to '
        '${_qualifiedName(mockNameFilter, logFilter.toString())} '
        '${isPreceding?"preceding":"following"} ${keys.filter}';

    LogEntryList rtn = new LogEntryList(filterName);

    // Deal with the trivial case.
    if (logs.length == 0 || keys.logs.length == 0) {
      return rtn;
    }

    // Normalize the mockNameFilter and logFilter values.
    if (mockNameFilter == null) {
      mockNameFilter = anything;
    } else {
      mockNameFilter = wrapMatcher(mockNameFilter);
    }
    logFilter = _makePredicate(logFilter);

    // The scratch list is used to hold matching entries when we
    // are doing preceding neighbors. The remainingCount is used to
    // keep track of how many matching entries we can still add in the
    // current segment (0 if we are doing doing following neighbors, until
    // we get our first key match).
    List scratch = null;
    int remainingCount = 0;
    if (isPreceding) {
      scratch = new List();
      remainingCount = logs.length;
    }

    var keyIterator = keys.logs.iterator;
    keyIterator.moveNext();
    LogEntry keyEntry = keyIterator.current;
    MatchState matchState = new MatchState();

    for (LogEntry logEntry in logs) {
      // If we have a log entry match, copy the saved matches from the
      // scratch buffer into the return list, as well as the matching entry,
      // if appropriate, and reset the scratch buffer. Continue processing
      // from the next key entry.
      if (keyEntry == logEntry) {
        if (scratch != null) {
          int numToCopy = scratch.length;
          if (distance > 0 && distance < numToCopy) {
            numToCopy = distance;
          }
          for (var i = scratch.length - numToCopy; i < scratch.length; i++) {
            rtn.logs.add(scratch[i]);
          }
          scratch.clear();
        } else {
          remainingCount = distance > 0 ? distance : logs.length;
        }
        if (includeKeys) {
          rtn.logs.add(keyEntry);
        }
        if (keyIterator.moveNext()) {
          keyEntry = keyIterator.current;
        } else if (isPreceding) { // We're done.
          break;
        }
      } else if (remainingCount > 0 &&
                 mockNameFilter.matches(logEntry.mockName, matchState) &&
                 logFilter(logEntry)) {
        if (scratch != null) {
          scratch.add(logEntry);
        } else {
          rtn.logs.add(logEntry);
          --remainingCount;
        }
      }
    }
    return rtn;
  }

  /**
   * Iterate through the LogEntryList looking for matches to the entries
   * in [keys]; for each match found the closest [distance] prior log entries
   * that match [mocknameFilter] and [logFilter] will be included in the result.
   * If [includeKeys] is true then the entries in [keys] that resulted in
   * entries in the output list are themselves included in the output list. If
   * [distance] is zero then all matches are included.
   *
   * The idea here is that you could find log entries that are related to
   * other logs entries in some temporal sense. For example, say we have a
   * method commit() that returns -1 on failure. Before commit() gets called
   * the value being committed is created by process(). We may want to find
   * the calls to process() that preceded calls to commit() that failed.
   * We could do this with:
   *
   *      print(log.preceding(log.getLogs(callsTo('commit'), returning(-1)),
   *          logFilter: callsTo('process')).toString());
   *
   * We might want to include the details of the failing calls to commit()
   * to see what parameters were passed in, in which case we would set
   * [includeKeys].
   *
   * As another simple example, say we wanted to know the three method
   * calls that immediately preceded each failing call to commit():
   *
   *     print(log.preceding(log.getLogs(callsTo('commit'), returning(-1)),
   *         distance: 3).toString());
   */
  LogEntryList preceding(LogEntryList keys,
                         {mockNameFilter: null,
                         logFilter: null,
                         int distance: 1,
                         bool includeKeys: false}) =>
      _neighboring(true, keys, mockNameFilter, logFilter,
          distance, includeKeys);

  /**
   * Iterate through the LogEntryList looking for matches to the entries
   * in [keys]; for each match found the closest [distance] subsequent log
   * entries that match [mocknameFilter] and [logFilter] will be included in
   * the result. If [includeKeys] is true then the entries in [keys] that
   * resulted in entries in the output list are themselves included in the
   * output list. If [distance] is zero then all matches are included.
   * See [preceding] for a usage example.
   */
  LogEntryList following(LogEntryList keys,
                         {mockNameFilter: null,
                         logFilter: null,
                         int distance: 1,
                         bool includeKeys: false}) =>
      _neighboring(false, keys, mockNameFilter, logFilter,
          distance, includeKeys);
}

/**
 * [_TimesMatcher]s are used to make assertions about the number of
 * times a method was called.
 */
class _TimesMatcher extends BaseMatcher {
  final int min, max;

  const _TimesMatcher(this.min, [this.max = -1]);

  bool matches(logList, MatchState matchState) => logList.length >= min &&
      (max < 0 || logList.length <= max);

  Description describe(Description description) {
    description.add('to be called ');
    if (max < 0) {
      description.add('at least $min');
    } else if (max == min) {
      description.add('$max');
    } else if (min == 0) {
      description.add('at most $max');
    } else {
      description.add('between $min and $max');
    }
    return description.add(' times');
  }

  Description describeMismatch(logList, Description mismatchDescription,
                               MatchState matchState, bool verbose) =>
      mismatchDescription.add('was called ${logList.length} times');
}

/** [happenedExactly] matches an exact number of calls. */
Matcher happenedExactly(count) {
  return new _TimesMatcher(count, count);
}

/** [happenedAtLeast] matches a minimum number of calls. */
Matcher happenedAtLeast(count) {
  return new _TimesMatcher(count);
}

/** [happenedAtMost] matches a maximum number of calls. */
Matcher happenedAtMost(count) {
  return new _TimesMatcher(0, count);
}

/** [neverHappened] matches zero calls. */
const Matcher neverHappened = const _TimesMatcher(0, 0);

/** [happenedOnce] matches exactly one call. */
const Matcher happenedOnce = const _TimesMatcher(1, 1);

/** [happenedAtLeastOnce] matches one or more calls. */
const Matcher happenedAtLeastOnce = const _TimesMatcher(1);

/** [happenedAtMostOnce] matches zero or one call. */
const Matcher happenedAtMostOnce = const _TimesMatcher(0, 1);

/**
 * [_ResultMatcher]s are used to make assertions about the results
 * of method calls. These can be used as optional parameters to [getLogs].
 */
class _ResultMatcher extends BaseMatcher {
  final Action action;
  final Matcher value;

  const _ResultMatcher(this.action, this.value);

  bool matches(item, MatchState matchState) {
    if (item is! LogEntry) {
     return false;
    }
    // normalize the action; _PROXY is like _RETURN.
    Action eaction = item.action;
    if (eaction == Action.PROXY) {
      eaction = Action.RETURN;
    }
    return (eaction == action && value.matches(item.value, matchState));
  }

  Description describe(Description description) {
    description.add(' to ');
    if (action == Action.RETURN || action == Action.PROXY)
      description.add('return ');
    else
      description.add('throw ');
    return description.addDescriptionOf(value);
  }

  Description describeMismatch(item, Description mismatchDescription,
                               MatchState matchState, bool verbose) {
    if (item.action == Action.RETURN || item.action == Action.PROXY) {
      mismatchDescription.add('returned ');
    } else {
      mismatchDescription.add('threw ');
    }
    mismatchDescription.add(item.value);
    return mismatchDescription;
  }
}

/**
 *[returning] matches log entries where the call to a method returned
 * a value that matched [value].
 */
Matcher returning(value) =>
    new _ResultMatcher(Action.RETURN, wrapMatcher(value));

/**
 *[throwing] matches log entrues where the call to a method threw
 * a value that matched [value].
 */
Matcher throwing(value) =>
    new _ResultMatcher(Action.THROW, wrapMatcher(value));

/** Special values for use with [_ResultSetMatcher] [frequency]. */
class _Frequency {
  /** Every call/throw must match */
  static const ALL = const _Frequency._('ALL');

  /** At least one call/throw must match. */
  static const SOME = const _Frequency._('SOME');

  /** No calls/throws should match. */
  static const NONE = const _Frequency._('NONE');

  const _Frequency._(this.name);

  final String name;
}

/**
 * [_ResultSetMatcher]s are used to make assertions about the results
 * of method calls. When filtering an execution log by calling
 * [getLogs], a [LogEntrySet] of matching call logs is returned;
 * [_ResultSetMatcher]s can then assert various things about this
 * (sub)set of logs.
 *
 * We could make this class use _ResultMatcher but it doesn't buy that
 * match and adds some perf hit, so there is some duplication here.
 */
class _ResultSetMatcher extends BaseMatcher {
  final Action action;
  final Matcher value;
  final _Frequency frequency; // ALL, SOME, or NONE.

  const _ResultSetMatcher(this.action, this.value, this.frequency);

  bool matches(logList, MatchState matchState) {
    for (LogEntry entry in logList) {
      // normalize the action; PROXY is like RETURN.
      Action eaction = entry.action;
      if (eaction == Action.PROXY) {
        eaction = Action.RETURN;
      }
      if (eaction == action && value.matches(entry.value, matchState)) {
        if (frequency == _Frequency.NONE) {
          matchState.state = {
              'state' : matchState.state,
              'entry' : entry
          };
          return false;
        } else if (frequency == _Frequency.SOME) {
          return true;
        }
      } else {
        // Mismatch.
        if (frequency == _Frequency.ALL) { // We need just one mismatch to fail.
          matchState.state = {
              'state' : matchState.state,
              'entry' : entry
          };
          return false;
        }
      }
    }
    // If we get here, then if count is _ALL we got all matches and
    // this is success; otherwise we got all mismatched which is
    // success for count == _NONE and failure for count == _SOME.
    return (frequency != _Frequency.SOME);
  }

  Description describe(Description description) {
    description.add(' to ');
    description.add(frequency == _Frequency.ALL ? 'alway ' :
        (frequency == _Frequency.NONE ? 'never ' : 'sometimes '));
    if (action == Action.RETURN || action == Action.PROXY)
      description.add('return ');
    else
      description.add('throw ');
    return description.addDescriptionOf(value);
  }

  Description describeMismatch(logList, Description mismatchDescription,
                               MatchState matchState, bool verbose) {
    if (frequency != _Frequency.SOME) {
      LogEntry entry = matchState.state['entry'];
      if (entry.action == Action.RETURN || entry.action == Action.PROXY) {
        mismatchDescription.add('returned');
      } else {
        mismatchDescription.add('threw');
      }
      mismatchDescription.add(' value that ');
      value.describeMismatch(entry.value, mismatchDescription,
        matchState.state['state'], verbose);
      mismatchDescription.add(' at least once');
    } else {
      mismatchDescription.add('never did');
    }
    return mismatchDescription;
  }
}

/**
 *[alwaysReturned] asserts that all matching calls to a method returned
 * a value that matched [value].
 */
Matcher alwaysReturned(value) =>
    new _ResultSetMatcher(Action.RETURN, wrapMatcher(value), _Frequency.ALL);

/**
 *[sometimeReturned] asserts that at least one matching call to a method
 * returned a value that matched [value].
 */
Matcher sometimeReturned(value) =>
    new _ResultSetMatcher(Action.RETURN, wrapMatcher(value), _Frequency.SOME);

/**
 *[neverReturned] asserts that no matching calls to a method returned
 * a value that matched [value].
 */
Matcher neverReturned(value) =>
    new _ResultSetMatcher(Action.RETURN, wrapMatcher(value), _Frequency.NONE);

/**
 *[alwaysThrew] asserts that all matching calls to a method threw
 * a value that matched [value].
 */
Matcher alwaysThrew(value) =>
    new _ResultSetMatcher(Action.THROW, wrapMatcher(value), _Frequency.ALL);

/**
 *[sometimeThrew] asserts that at least one matching call to a method threw
 * a value that matched [value].
 */
Matcher sometimeThrew(value) =>
  new _ResultSetMatcher(Action.THROW, wrapMatcher(value), _Frequency.SOME);

/**
 *[neverThrew] asserts that no matching call to a method threw
 * a value that matched [value].
 */
Matcher neverThrew(value) =>
  new _ResultSetMatcher(Action.THROW, wrapMatcher(value), _Frequency.NONE);

/** The shared log used for named mocks. */
LogEntryList sharedLog = null;

/** The base class for all mocked objects. */
class Mock {
  /** The mock name. Needed if the log is shared; optional otherwise. */
  final String name;

  /** The set of [Behavior]s supported. */
  Map<String,Behavior> _behaviors;

  /** The [log] of calls made. Only used if [name] is null. */
  LogEntryList log;

  /** How to handle unknown method calls - swallow or throw. */
  final bool _throwIfNoBehavior;

  /** Whether to create an audit log or not. */
  bool _logging;

  bool get logging => _logging;
  set logging(bool value) {
    if (value && log == null) {
      log = new LogEntryList();
    }
    _logging = value;
  }

  /**
   * Default constructor. Unknown method calls are allowed and logged,
   * the mock has no name, and has its own log.
   */
  Mock() : _throwIfNoBehavior = false, log = null, name = null {
    logging = true;
    _behaviors = new Map<String,Behavior>();
  }

  /**
   * This constructor makes a mock that has a [name] and possibly uses
   * a shared [log]. If [throwIfNoBehavior] is true, any calls to methods
   * that have no defined behaviors will throw an exception; otherwise they
   * will be allowed and logged (but will not do anything).
   * If [enableLogging] is false, no logging will be done initially (whether
   * or not a [log] is supplied), but [logging] can be set to true later.
   */
  Mock.custom({this.name,
               this.log,
               throwIfNoBehavior: false,
               enableLogging: true}) : _throwIfNoBehavior = throwIfNoBehavior {
    if (log != null && name == null) {
      throw new Exception("Mocks with shared logs must have a name.");
    }
    logging = enableLogging;
    _behaviors = new Map<String,Behavior>();
  }

  /**
   * [when] is used to create a new or extend an existing [Behavior].
   * A [CallMatcher] [filter] must be supplied, and the [Behavior]s for
   * that signature are returned (being created first if needed).
   *
   * Typical use case:
   *
   *     mock.when(callsTo(...)).alwaysReturn(...);
   */
  Behavior when(CallMatcher logFilter) {
    String key = logFilter.toString();
    if (!_behaviors.containsKey(key)) {
      Behavior b = new Behavior(logFilter);
      _behaviors[key] = b;
      return b;
    } else {
      return _behaviors[key];
    }
  }

  /**
   * This is the handler for method calls. We loop through the list
   * of [Behavior]s, and find the first match that still has return
   * values available, and then do the action specified by that
   * return value. If we find no [Behavior] to apply an exception is
   * thrown.
   */
  noSuchMethod(Invocation invocation) {
    var method = MirrorSystem.getName(invocation.memberName);
    var args = invocation.positionalArguments;
    if (invocation.isGetter) {
      method = 'get $method';
    } else if (invocation.isSetter) {
      method = 'set $method';
      // Remove the trailing '='.
      if (method[method.length-1] == '=') {
        method = method.substring(0, method.length - 1);
      }
    }
    bool matchedMethodName = false;
    MatchState matchState = new MatchState();
    for (String k in _behaviors.keys) {
      Behavior b = _behaviors[k];
      if (b.matcher.nameFilter.matches(method, matchState)) {
        matchedMethodName = true;
      }
      if (b.matches(method, args)) {
        List actions = b.actions;
        if (actions == null || actions.length == 0) {
          continue; // No return values left in this Behavior.
        }
        // Get the first response.
        Responder response = actions[0];
        // If it is exhausted, remove it from the list.
        // Note that for endlessly repeating values, we started the count at
        // 0, so we get a potentially useful value here, which is the
        // (negation of) the number of times we returned the value.
        if (--response.count == 0) {
          actions.removeRange(0, 1);
        }
        // Do the response.
        Action action = response.action;
        var value = response.value;
        if (action == Action.RETURN) {
          if (_logging && b.logging) {
            log.add(new LogEntry(name, method, args, action, value));
          }
          return value;
        } else if (action == Action.THROW) {
          if (_logging && b.logging) {
            log.add(new LogEntry(name, method, args, action, value));
          }
          throw value;
        } else if (action == Action.PROXY) {
          // TODO(gram): Replace all this with:
          //     var rtn = invocation.invokeOn(value);
          // once that is supported.
          var rtn;
          switch (args.length) {
            case 0:
              rtn = value();
              break;
            case 1:
              rtn = value(args[0]);
              break;
            case 2:
              rtn = value(args[0], args[1]);
              break;
            case 3:
              rtn = value(args[0], args[1], args[2]);
              break;
            case 4:
              rtn = value(args[0], args[1], args[2], args[3]);
              break;
            case 5:
              rtn = value(args[0], args[1], args[2], args[3], args[4]);
              break;
            case 6:
              rtn = value(args[0], args[1], args[2], args[3],
                  args[4], args[5]);
              break;
            case 7:
              rtn = value(args[0], args[1], args[2], args[3],
                  args[4], args[5], args[6]);
              break;
            case 8:
              rtn = value(args[0], args[1], args[2], args[3],
                  args[4], args[5], args[6], args[7]);
              break;
            case 9:
              rtn = value(args[0], args[1], args[2], args[3],
                  args[4], args[5], args[6], args[7], args[8]);
              break;
            case 9:
              rtn = value(args[0], args[1], args[2], args[3],
                  args[4], args[5], args[6], args[7], args[8], args[9]);
              break;
            default:
              throw new Exception(
                  "Cannot proxy calls with more than 10 parameters.");
          }
          if (_logging && b.logging) {
            log.add(new LogEntry(name, method, args, action, rtn));
          }
          return rtn;
        }
      }
    }
    if (matchedMethodName) {
      // User did specify behavior for this method, but all the
      // actions are exhausted. This is considered an error.
      throw new Exception('No more actions for method '
          '${_qualifiedName(name, method)}.');
    } else if (_throwIfNoBehavior) {
      throw new Exception('No behavior specified for method '
          '${_qualifiedName(name, method)}.');
    }
    // Otherwise user hasn't specified behavior for this method; we don't throw
    // so we can underspecify.
    if (_logging) {
      log.add(new LogEntry(name, method, args, Action.IGNORE));
    }
  }

  /** [verifyZeroInteractions] returns true if no calls were made */
  bool verifyZeroInteractions() {
    if (log == null) {
      // This means we created the mock with logging off and have never turned
      // it on, so it doesn't make sense to verify behavior on such a mock.
      throw new
          Exception("Can't verify behavior when logging was never enabled.");
    }
    return log.logs.length == 0;
  }

  /**
   * [getLogs] extracts all calls from the call log that match the
   * [logFilter], and returns the matching list of [LogEntry]s. If
   * [destructive] is false (the default) the matching calls are left
   * in the log, else they are removed. Removal allows us to verify a
   * set of interactions and then verify that there are no other
   * interactions left. [actionMatcher] can be used to further
   * restrict the returned logs based on the action the mock performed.
   * [logFilter] can be a [CallMatcher] or a predicate function that
   * takes a [LogEntry] and returns a bool.
   *
   * Typical usage:
   *
   *     getLogs(callsTo(...)).verify(...);
   */
  LogEntryList getLogs([CallMatcher logFilter,
                        Matcher actionMatcher,
                        bool destructive = false]) {
    if (log == null) {
      // This means we created the mock with logging off and have never turned
      // it on, so it doesn't make sense to get logs from such a mock.
      throw new
          Exception("Can't retrieve logs when logging was never enabled.");
    } else {
      return log.getMatches(name, logFilter, actionMatcher, destructive);
    }
  }

  /**
   * Useful shorthand method that creates a [CallMatcher] from its arguments
   * and then calls [getLogs].
   */
  LogEntryList calls(method,
                      [arg0 = _noArg,
                       arg1 = _noArg,
                       arg2 = _noArg,
                       arg3 = _noArg,
                       arg4 = _noArg,
                       arg5 = _noArg,
                       arg6 = _noArg,
                       arg7 = _noArg,
                       arg8 = _noArg,
                       arg9 = _noArg]) =>
      getLogs(callsTo(method, arg0, arg1, arg2, arg3, arg4,
          arg5, arg6, arg7, arg8, arg9));

  /** Clear the behaviors for the Mock. */
  void resetBehavior() => _behaviors.clear();

  /** Clear the logs for the Mock. */
  void clearLogs() {
    if (log != null) {
      if (name == null) { // This log is not shared.
        log.logs.clear();
      } else { // This log may be shared.
        log.logs = log.logs.where((e) => e.mockName != name).toList();
      }
    }
  }

  /** Clear both logs and behavior. */
  void reset() {
    resetBehavior();
    clearLogs();
  }
}
