// Copyright (c) 2019, 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 'dart:async';

import 'common_callbacks.dart';

extension AggregateSample<T> on Stream<T> {
  /// Computes a value based on sequences of events, then emits that value when
  /// [trigger] emits an event.
  ///
  /// Every time this stream emits an event, an intermediate value is created
  /// by combining the new event with the previous intermediate value, or with
  /// `null` if there is no previous value, using the [aggregate] function.
  ///
  /// When [trigger] emits value, the returned stream emits the current
  /// intermediate value and clears it.
  ///
  /// If [longPoll] is `false`, if there is no intermediate value when [trigger]
  /// emits an event, the [onEmpty] function is called with a [Sink] which can
  /// add events to the returned stream.
  ///
  /// If [longPoll] is `true`, and there is no intermediate value when [trigger]
  /// emits one or more events, then the *next* event from this stream is
  /// immediately put through [aggregate] and emitted on the returned stream.
  /// Subsequent events on [trigger] while there have been no events on this
  /// stream are ignored.
  /// In that case, [onEmpty] is never used.
  ///
  /// The result stream will close as soon as there is a guarantee it will not
  /// emit any more events. There will not be any more events emitted if:
  /// - [trigger] is closed and there is no waiting long poll.
  /// - Or, the source stream is closed and there are no buffered events.
  ///
  /// If the source stream is a broadcast stream, the result will be as well.
  /// Errors from the source stream or the trigger are immediately forwarded to
  /// the output.
  Stream<S> aggregateSample<S>(
      {required Stream<void> trigger,
      required S Function(T, S?) aggregate,
      required bool longPoll,
      required void Function(Sink<S>) onEmpty}) {
    var controller = isBroadcast
        ? StreamController<S>.broadcast(sync: true)
        : StreamController<S>(sync: true);

    S? currentResults;
    var hasCurrentResults = false;
    var activeLongPoll = false;
    var isTriggerDone = false;
    var isValueDone = false;
    StreamSubscription<T>? valueSub;
    StreamSubscription<void>? triggerSub;

    void emit(S results) {
      currentResults = null;
      hasCurrentResults = false;
      controller.add(results);
    }

    void onValue(T value) {
      currentResults = aggregate(value, currentResults);
      hasCurrentResults = true;
      if (!longPoll) return;

      if (activeLongPoll) {
        activeLongPoll = false;
        emit(currentResults as S);
      }

      if (isTriggerDone) {
        valueSub!.cancel();
        controller.close();
      }
    }

    void onValuesDone() {
      isValueDone = true;
      if (!hasCurrentResults) {
        triggerSub?.cancel();
        controller.close();
      }
    }

    void onTrigger(_) {
      if (hasCurrentResults) {
        emit(currentResults as S);
      } else if (longPoll) {
        activeLongPoll = true;
      } else {
        onEmpty(controller);
      }

      if (isValueDone) {
        triggerSub!.cancel();
        controller.close();
      }
    }

    void onTriggerDone() {
      isTriggerDone = true;
      if (!activeLongPoll) {
        valueSub?.cancel();
        controller.close();
      }
    }

    controller.onListen = () {
      assert(valueSub == null);
      valueSub =
          listen(onValue, onError: controller.addError, onDone: onValuesDone);
      final priorTriggerSub = triggerSub;
      if (priorTriggerSub != null) {
        if (priorTriggerSub.isPaused) priorTriggerSub.resume();
      } else {
        triggerSub = trigger.listen(onTrigger,
            onError: controller.addError, onDone: onTriggerDone);
      }
      if (!isBroadcast) {
        controller
          ..onPause = () {
            valueSub?.pause();
            triggerSub?.pause();
          }
          ..onResume = () {
            valueSub?.resume();
            triggerSub?.resume();
          };
      }
      controller.onCancel = () {
        var cancels = <Future<void>>[if (!isValueDone) valueSub!.cancel()];
        valueSub = null;
        if (trigger.isBroadcast || !isBroadcast) {
          if (!isTriggerDone) cancels.add(triggerSub!.cancel());
          triggerSub = null;
        } else {
          triggerSub!.pause();
        }
        if (cancels.isEmpty) return null;
        return cancels.wait.then(ignoreArgument);
      };
    };
    return controller.stream;
  }
}
