// Copyright (c) 2014, 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 mock.log_entry_list;

import 'package:matcher/matcher.dart';

import 'call_matcher.dart';
import 'log_entry.dart';
import 'util.dart';

/**
* [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);
    var 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;
    Map 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);
}

_MockFailureHandler _mockFailureHandler = null;

/**
 * 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,
                 Map matchState, bool verbose) {
    proxy.fail(_mockingErrorFormatter(actual, matcher, reason,
        matchState, verbose));
  }
}

/**
 * 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,
                              Map 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();
}
