// Copyright (c) 2017, 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.

import 'package:async/async.dart';

import '../description.dart';
import '../interfaces.dart';
import '../util.dart';
import 'async_matcher.dart';
import 'stream_matcher.dart';
import 'throws_matcher.dart';
import 'util/pretty_print.dart';

/// Returns a [StreamMatcher] that asserts that the stream emits a "done" event.
final emitsDone = StreamMatcher(
    (queue) async => (await queue.hasNext) ? '' : null, 'be done');

/// Returns a [StreamMatcher] for [matcher].
///
/// If [matcher] is already a [StreamMatcher], it's returned as-is. If it's any
/// other [Matcher], this matches a single event that matches that matcher. If
/// it's any other Object, this matches a single event that's equal to that
/// object.
///
/// This functions like [wrapMatcher] for [StreamMatcher]s: it can convert any
/// matcher-like value into a proper [StreamMatcher].
StreamMatcher emits(Object? matcher) {
  if (matcher is StreamMatcher) return matcher;
  var wrapped = wrapMatcher(matcher);

  var matcherDescription = wrapped.describe(StringDescription());

  return StreamMatcher((queue) async {
    if (!await queue.hasNext) return '';

    var matchState = <Object?, Object?>{};
    var actual = await queue.next;
    if (wrapped.matches(actual, matchState)) return null;

    var mismatchDescription = StringDescription();
    wrapped.describeMismatch(actual, mismatchDescription, matchState, false);

    if (mismatchDescription.length == 0) return '';
    return 'emitted an event that $mismatchDescription';
  },
      // TODO(nweiz): add "should" once matcher#42 is fixed.
      'emit an event that $matcherDescription');
}

/// Returns a [StreamMatcher] that matches a single error event that matches
/// [matcher].
StreamMatcher emitsError(Object? matcher) {
  var wrapped = wrapMatcher(matcher);
  var matcherDescription = wrapped.describe(StringDescription());
  var throwsMatcher = throwsA(wrapped) as AsyncMatcher;

  return StreamMatcher(
      (queue) => throwsMatcher.matchAsync(queue.next) as Future<String?>,
      // TODO(nweiz): add "should" once matcher#42 is fixed.
      'emit an error that $matcherDescription');
}

/// Returns a [StreamMatcher] that allows (but doesn't require) [matcher] to
/// match the stream.
///
/// This matcher always succeeds; if [matcher] doesn't match, this just consumes
/// no events.
StreamMatcher mayEmit(Object? matcher) {
  var streamMatcher = emits(matcher);
  return StreamMatcher((queue) async {
    await queue.withTransaction(
        (copy) async => (await streamMatcher.matchQueue(copy)) == null);
    return null;
  }, 'maybe ${streamMatcher.description}');
}

/// Returns a [StreamMatcher] that matches the stream if at least one of
/// [matchers] matches.
///
/// If multiple matchers match the stream, this chooses the matcher that
/// consumes as many events as possible.
///
/// If any matchers match the stream, no errors from other matchers are thrown.
/// If no matchers match and multiple matchers threw errors, the first error is
/// re-thrown.
StreamMatcher emitsAnyOf(Iterable matchers) {
  var streamMatchers = matchers.map(emits).toList();
  if (streamMatchers.isEmpty) {
    throw ArgumentError('matcher may not be empty');
  }

  if (streamMatchers.length == 1) return streamMatchers.first;
  var description = 'do one of the following:\n'
      '${bullet(streamMatchers.map((matcher) => matcher.description))}';

  return StreamMatcher((queue) async {
    var transaction = queue.startTransaction();

    // Allocate the failures list ahead of time so that its order matches the
    // order of [matchers], and thus the order the matchers will be listed in
    // the description.
    var failures = List<String?>.filled(matchers.length, null);

    // The first error thrown. If no matchers match and this exists, we rethrow
    // it.
    Object? firstError;
    StackTrace? firstStackTrace;

    var futures = <Future>[];
    StreamQueue? consumedMost;
    for (var i = 0; i < matchers.length; i++) {
      futures.add(() async {
        var copy = transaction.newQueue();

        String? result;
        try {
          result = await streamMatchers[i].matchQueue(copy);
        } catch (error, stackTrace) {
          if (firstError == null) {
            firstError = error;
            firstStackTrace = stackTrace;
          }
          return;
        }

        if (result != null) {
          failures[i] = result;
        } else if (consumedMost == null ||
            consumedMost!.eventsDispatched < copy.eventsDispatched) {
          consumedMost = copy;
        }
      }());
    }

    await Future.wait(futures);

    if (consumedMost == null) {
      transaction.reject();
      if (firstError != null) {
        await Future<Never>.error(firstError!, firstStackTrace);
      }

      var failureMessages = <String>[];
      for (var i = 0; i < matchers.length; i++) {
        var message = 'failed to ${streamMatchers[i].description}';
        if (failures[i]!.isNotEmpty) {
          message += message.contains('\n') ? '\n' : ' ';
          message += 'because it ${failures[i]}';
        }

        failureMessages.add(message);
      }

      return 'failed all options:\n${bullet(failureMessages)}';
    } else {
      transaction.commit(consumedMost!);
      return null;
    }
  }, description);
}

/// Returns a [StreamMatcher] that matches the stream if each matcher in
/// [matchers] matches, one after another.
///
/// If any matcher fails to match, this fails and consumes no events.
StreamMatcher emitsInOrder(Iterable matchers) {
  var streamMatchers = matchers.map(emits).toList();
  if (streamMatchers.length == 1) return streamMatchers.first;

  var description = 'do the following in order:\n'
      '${bullet(streamMatchers.map((matcher) => matcher.description))}';

  return StreamMatcher((queue) async {
    for (var i = 0; i < streamMatchers.length; i++) {
      var matcher = streamMatchers[i];
      var result = await matcher.matchQueue(queue);
      if (result == null) continue;

      var newResult = "didn't ${matcher.description}";
      if (result.isNotEmpty) {
        newResult += newResult.contains('\n') ? '\n' : ' ';
        newResult += 'because it $result';
      }
      return newResult;
    }
    return null;
  }, description);
}

/// Returns a [StreamMatcher] that matches any number of events followed by
/// events that match [matcher].
///
/// This consumes all events matched by [matcher], as well as all events before.
/// If the stream emits a done event without matching [matcher], this fails and
/// consumes no events.
StreamMatcher emitsThrough(Object? matcher) {
  var streamMatcher = emits(matcher);
  return StreamMatcher((queue) async {
    var failures = <String>[];

    Future<bool> tryHere() => queue.withTransaction((copy) async {
          var result = await streamMatcher.matchQueue(copy);
          if (result == null) return true;
          failures.add(result);
          return false;
        });

    while (await queue.hasNext) {
      if (await tryHere()) return null;
      await queue.next;
    }

    // Try after the queue is done in case the matcher can match an empty
    // stream.
    if (await tryHere()) return null;

    var result = 'never did ${streamMatcher.description}';

    var failureMessages =
        bullet(failures.where((failure) => failure.isNotEmpty));
    if (failureMessages.isNotEmpty) {
      result += result.contains('\n') ? '\n' : ' ';
      result += 'because it:\n$failureMessages';
    }

    return result;
  }, 'eventually ${streamMatcher.description}');
}

/// Returns a [StreamMatcher] that matches any number of events that match
/// [matcher].
///
/// This consumes events until [matcher] no longer matches. It always succeeds;
/// if [matcher] doesn't match, this just consumes no events. It never rethrows
/// errors.
StreamMatcher mayEmitMultiple(Object? matcher) {
  var streamMatcher = emits(matcher);

  var description = streamMatcher.description;
  description += description.contains('\n') ? '\n' : ' ';
  description += 'zero or more times';

  return StreamMatcher((queue) async {
    while (await _tryMatch(queue, streamMatcher)) {
      // Do nothing; the matcher presumably already consumed events.
    }
    return null;
  }, description);
}

/// Returns a [StreamMatcher] that matches a stream that never matches
/// [matcher].
///
/// This doesn't complete until the stream emits a done event. It never consumes
/// any events. It never re-throws errors.
StreamMatcher neverEmits(Object? matcher) {
  var streamMatcher = emits(matcher);
  return StreamMatcher((queue) async {
    var events = 0;
    var matched = false;
    await queue.withTransaction((copy) async {
      while (await copy.hasNext) {
        matched = await _tryMatch(copy, streamMatcher);
        if (matched) return false;

        events++;

        try {
          await copy.next;
        } catch (_) {
          // Ignore errors events.
        }
      }

      matched = await _tryMatch(copy, streamMatcher);
      return false;
    });

    if (!matched) return null;
    return "after $events ${pluralize('event', events)} did "
        '${streamMatcher.description}';
  }, 'never ${streamMatcher.description}');
}

/// Returns whether [matcher] matches [queue] at its current position.
///
/// This treats errors as failures to match.
Future<bool> _tryMatch(StreamQueue queue, StreamMatcher matcher) {
  return queue.withTransaction((copy) async {
    try {
      return (await matcher.matchQueue(copy)) == null;
    } catch (_) {
      return false;
    }
  });
}

/// Returns a [StreamMatcher] that matches the stream if each matcher in
/// [matchers] matches, in any order.
///
/// If any matcher fails to match, this fails and consumes no events. If the
/// matchers match in multiple different possible orders, this chooses the order
/// that consumes as many events as possible.
///
/// If any sequence of matchers matches the stream, no errors from other
/// sequences are thrown. If no sequences match and multiple sequences throw
/// errors, the first error is re-thrown.
///
/// Note that checking every ordering of [matchers] is O(n!) in the worst case,
/// so this should only be called when there are very few [matchers].
StreamMatcher emitsInAnyOrder(Iterable matchers) {
  var streamMatchers = matchers.map(emits).toSet();
  if (streamMatchers.length == 1) return streamMatchers.first;
  var description = 'do the following in any order:\n'
      '${bullet(streamMatchers.map((matcher) => matcher.description))}';

  return StreamMatcher(
      (queue) async => await _tryInAnyOrder(queue, streamMatchers) ? null : '',
      description);
}

/// Returns whether [queue] matches [matchers] in any order.
Future<bool> _tryInAnyOrder(
    StreamQueue queue, Set<StreamMatcher> matchers) async {
  if (matchers.length == 1) {
    return await matchers.first.matchQueue(queue) == null;
  }

  var transaction = queue.startTransaction();
  StreamQueue? consumedMost;

  // The first error thrown. If no matchers match and this exists, we rethrow
  // it.
  Object? firstError;
  StackTrace? firstStackTrace;

  await Future.wait(matchers.map((matcher) async {
    var copy = transaction.newQueue();
    try {
      if (await matcher.matchQueue(copy) != null) return;
    } catch (error, stackTrace) {
      if (firstError == null) {
        firstError = error;
        firstStackTrace = stackTrace;
      }
      return;
    }

    var rest = Set<StreamMatcher>.from(matchers);
    rest.remove(matcher);

    try {
      if (!await _tryInAnyOrder(copy, rest)) return;
    } catch (error, stackTrace) {
      if (firstError == null) {
        firstError = error;
        firstStackTrace = stackTrace;
      }
      return;
    }

    if (consumedMost == null ||
        consumedMost!.eventsDispatched < copy.eventsDispatched) {
      consumedMost = copy;
    }
  }));

  if (consumedMost == null) {
    transaction.reject();
    if (firstError != null) {
      await Future<Never>.error(firstError!, firstStackTrace);
    }
    return false;
  } else {
    transaction.commit(consumedMost!);
    return true;
  }
}
