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

part of dart.async;

class _BroadcastStream<T> extends _ControllerStream<T> {
  _BroadcastStream(_StreamControllerLifecycle<T> controller)
    : super(controller);

  bool get isBroadcast => true;
}

class _BroadcastSubscription<T> extends _ControllerSubscription<T> {
  static const int _STATE_EVENT_ID = 1;
  static const int _STATE_FIRING = 2;
  static const int _STATE_REMOVE_AFTER_FIRING = 4;
  // TODO(lrn): Use the _state field on _ControllerSubscription to
  // also store this state. Requires that the subscription implementation
  // does not assume that it's use of the state integer is the only use.
  int _eventState = 0; // Initialized to help dart2js type inference.

  _BroadcastSubscription<T>? _next;
  _BroadcastSubscription<T>? _previous;

  _BroadcastSubscription(
    _StreamControllerLifecycle<T> controller,
    void onData(T data)?,
    Function? onError,
    void onDone()?,
    bool cancelOnError,
  ) : super(controller, onData, onError, onDone, cancelOnError) {
    _next = _previous = this;
  }

  bool _expectsEvent(int eventId) => (_eventState & _STATE_EVENT_ID) == eventId;

  void _toggleEventId() {
    _eventState ^= _STATE_EVENT_ID;
  }

  bool get _isFiring => (_eventState & _STATE_FIRING) != 0;

  void _setRemoveAfterFiring() {
    assert(_isFiring);
    _eventState |= _STATE_REMOVE_AFTER_FIRING;
  }

  bool get _removeAfterFiring =>
      (_eventState & _STATE_REMOVE_AFTER_FIRING) != 0;

  // The controller._recordPause doesn't do anything for a broadcast controller,
  // so we don't bother calling it.
  void _onPause() {}

  // The controller._recordResume doesn't do anything for a broadcast
  // controller, so we don't bother calling it.
  void _onResume() {}

  // _onCancel is inherited.
}

abstract class _BroadcastStreamController<T>
    implements _StreamControllerBase<T> {
  static const int _STATE_INITIAL = 0;
  static const int _STATE_EVENT_ID = 1;
  static const int _STATE_FIRING = 2;
  static const int _STATE_CLOSED = 4;
  static const int _STATE_ADDSTREAM = 8;

  void Function()? onListen;
  FutureOr<void> Function()? onCancel;

  // State of the controller.
  int _state;

  // Double-linked list of active listeners.
  _BroadcastSubscription<T>? _firstSubscription;
  _BroadcastSubscription<T>? _lastSubscription;

  // Extra state used during an [addStream] call.
  _AddStreamState<T>? _addStreamState;

  /// Future returned by [close] and [done].
  ///
  /// The future is completed whenever the done event has been sent to all
  /// relevant listeners.
  /// The relevant listeners are the ones that were listening when [close] was
  /// called. When all of these have been canceled (sending the done event makes
  /// them cancel, but they can also be canceled before sending the event),
  /// this future completes.
  ///
  /// Any attempt to listen after calling [close] will throw, so there won't
  /// be any further listeners.
  _Future<void>? _doneFuture;

  _BroadcastStreamController(this.onListen, this.onCancel)
    : _state = _STATE_INITIAL;

  void Function() get onPause {
    throw UnsupportedError(
      "Broadcast stream controllers do not support pause callbacks",
    );
  }

  void set onPause(void onPauseHandler()?) {
    throw UnsupportedError(
      "Broadcast stream controllers do not support pause callbacks",
    );
  }

  void Function() get onResume {
    throw UnsupportedError(
      "Broadcast stream controllers do not support pause callbacks",
    );
  }

  void set onResume(void onResumeHandler()?) {
    throw UnsupportedError(
      "Broadcast stream controllers do not support pause callbacks",
    );
  }

  // StreamController interface.

  Stream<T> get stream => _BroadcastStream<T>(this);

  StreamSink<T> get sink => _StreamSinkWrapper<T>(this);

  bool get isClosed => (_state & _STATE_CLOSED) != 0;

  /// A broadcast controller is never paused.
  ///
  /// Each receiving stream may be paused individually, and they handle their
  /// own buffering.
  bool get isPaused => false;

  /// Whether there are currently one or more subscribers.
  bool get hasListener => !_isEmpty;

  /// Test whether the stream has exactly one listener.
  ///
  /// Assumes that the stream has a listener (not [_isEmpty]).
  bool get _hasOneListener {
    assert(!_isEmpty);
    return identical(_firstSubscription, _lastSubscription);
  }

  /// Whether an event is being fired (sent to some, but not all, listeners).
  bool get _isFiring => (_state & _STATE_FIRING) != 0;

  bool get _isAddingStream => (_state & _STATE_ADDSTREAM) != 0;

  bool get _mayAddEvent => (_state < _STATE_CLOSED);

  _Future<void> _ensureDoneFuture() => _doneFuture ??= _Future<void>();

  // Linked list helpers

  bool get _isEmpty => _firstSubscription == null;

  /// Adds subscription to linked list of active listeners.
  void _addListener(_BroadcastSubscription<T> subscription) {
    assert(identical(subscription._next, subscription));
    subscription._eventState = (_state & _STATE_EVENT_ID);
    // Insert in linked list as last subscription.
    _BroadcastSubscription<T>? oldLast = _lastSubscription;
    _lastSubscription = subscription;
    subscription._next = null;
    subscription._previous = oldLast;
    if (oldLast == null) {
      _firstSubscription = subscription;
    } else {
      oldLast._next = subscription;
    }
  }

  void _removeListener(_BroadcastSubscription<T> subscription) {
    assert(identical(subscription._controller, this));
    assert(!identical(subscription._next, subscription));
    _BroadcastSubscription<T>? previous = subscription._previous;
    _BroadcastSubscription<T>? next = subscription._next;
    if (previous == null) {
      // This was the first subscription.
      _firstSubscription = next;
    } else {
      previous._next = next;
    }
    if (next == null) {
      // This was the last subscription.
      _lastSubscription = previous;
    } else {
      next._previous = previous;
    }

    subscription._next = subscription._previous = subscription;
  }

  // _StreamControllerLifecycle interface.

  StreamSubscription<T> _subscribe(
    void onData(T data)?,
    Function? onError,
    void onDone()?,
    bool cancelOnError,
  ) {
    if (isClosed) {
      return _DoneStreamSubscription<T>(onDone);
    }
    var subscription = _BroadcastSubscription<T>(
      this,
      onData,
      onError,
      onDone,
      cancelOnError,
    );
    _addListener(subscription);
    if (identical(_firstSubscription, _lastSubscription)) {
      // Only one listener, so it must be the first listener.
      _runGuarded(onListen);
    }
    return subscription;
  }

  Future<void>? _recordCancel(StreamSubscription<T> sub) {
    _BroadcastSubscription<T> subscription = sub as _BroadcastSubscription<T>;
    // If already removed by the stream, don't remove it again.
    if (identical(subscription._next, subscription)) return null;
    if (subscription._isFiring) {
      subscription._setRemoveAfterFiring();
    } else {
      _removeListener(subscription);
      // If we are currently firing an event, the empty-check is performed at
      // the end of the listener loop instead of here.
      if (!_isFiring && _isEmpty) {
        _callOnCancel();
      }
    }
    return null;
  }

  void _recordPause(StreamSubscription<T> subscription) {}
  void _recordResume(StreamSubscription<T> subscription) {}

  // EventSink interface.

  Error _addEventError() {
    if (isClosed) {
      return StateError("Cannot add new events after calling close");
    }
    assert(_isAddingStream);
    return StateError("Cannot add new events while doing an addStream");
  }

  void add(T data) {
    if (!_mayAddEvent) throw _addEventError();
    _sendData(data);
  }

  void addError(Object error, [StackTrace? stackTrace]) {
    if (!_mayAddEvent) throw _addEventError();
    AsyncError(:error, :stackTrace) = _interceptUserError(error, stackTrace);
    _addError(error, stackTrace);
  }

  Future<void> close() {
    if (isClosed) {
      assert(_doneFuture != null);
      return _doneFuture!;
    }
    if (!_mayAddEvent) throw _addEventError();
    _state |= _STATE_CLOSED;
    var doneFuture = _ensureDoneFuture();
    _sendDone();
    return doneFuture;
  }

  Future<void> get done => _ensureDoneFuture();

  Future addStream(Stream<T> stream, {bool? cancelOnError}) {
    if (!_mayAddEvent) throw _addEventError();
    _state |= _STATE_ADDSTREAM;
    var addStreamState = _AddStreamState(this, stream, cancelOnError ?? false);
    _addStreamState = addStreamState;
    return addStreamState.addStreamFuture;
  }

  // _EventSink interface, called from AddStreamState.
  void _add(T data) {
    _sendData(data);
  }

  void _addError(Object error, StackTrace stackTrace) {
    _sendError(error, stackTrace);
  }

  void _close() {
    assert(_isAddingStream);
    _AddStreamState addState = _addStreamState!;
    _addStreamState = null;
    _state &= ~_STATE_ADDSTREAM;
    addState.complete();
  }

  // Event handling.
  void _forEachListener(
    void action(_BufferingStreamSubscription<T> subscription),
  ) {
    if (_isFiring) {
      throw StateError(
        "Cannot fire new event. Controller is already firing an event",
      );
    }
    if (_isEmpty) return;

    // Get event id of this event.
    int id = (_state & _STATE_EVENT_ID);
    // Start firing (set the _STATE_FIRING bit). We don't do [onCancel]
    // callbacks while firing, and we prevent reentrancy of this function.
    //
    // Set [_state]'s event id to the next event's id.
    // Any listeners added while firing this event will expect the next event,
    // not this one, and won't get notified.
    _state ^= _STATE_EVENT_ID | _STATE_FIRING;
    _BroadcastSubscription<T>? subscription = _firstSubscription;
    while (subscription != null) {
      if (subscription._expectsEvent(id)) {
        subscription._eventState |= _BroadcastSubscription._STATE_FIRING;
        action(subscription);
        subscription._toggleEventId();
        _BroadcastSubscription<T>? next = subscription._next;
        if (subscription._removeAfterFiring) {
          _removeListener(subscription);
        }
        subscription._eventState &= ~_BroadcastSubscription._STATE_FIRING;
        subscription = next;
      } else {
        subscription = subscription._next;
      }
    }
    _state &= ~_STATE_FIRING;

    if (_isEmpty) {
      _callOnCancel();
    }
  }

  void _callOnCancel() {
    assert(_isEmpty);
    if (isClosed) {
      // When closed, _doneFuture is not null.
      var doneFuture = _doneFuture!;
      if (doneFuture._mayComplete) {
        doneFuture._asyncComplete(null);
      }
    }
    _runGuarded(onCancel);
  }
}

class _SyncBroadcastStreamController<T> extends _BroadcastStreamController<T>
    implements SynchronousStreamController<T> {
  _SyncBroadcastStreamController(void onListen()?, void onCancel()?)
    : super(onListen, onCancel);

  // EventDispatch interface.

  bool get _mayAddEvent => super._mayAddEvent && !_isFiring;

  _addEventError() {
    if (_isFiring) {
      return StateError(
        "Cannot fire new event. Controller is already firing an event",
      );
    }
    return super._addEventError();
  }

  void _sendData(T data) {
    if (_isEmpty) return;
    if (_hasOneListener) {
      _state |= _BroadcastStreamController._STATE_FIRING;
      _BroadcastSubscription<T> firstSubscription =
          _firstSubscription as dynamic;
      firstSubscription._add(data);
      _state &= ~_BroadcastStreamController._STATE_FIRING;
      if (_isEmpty) {
        _callOnCancel();
      }
      return;
    }
    _forEachListener((_BufferingStreamSubscription<T> subscription) {
      subscription._add(data);
    });
  }

  void _sendError(Object error, StackTrace stackTrace) {
    if (_isEmpty) return;
    _forEachListener((_BufferingStreamSubscription<T> subscription) {
      subscription._addError(error, stackTrace);
    });
  }

  void _sendDone() {
    if (!_isEmpty) {
      _forEachListener((_BufferingStreamSubscription<T> subscription) {
        subscription._close();
      });
    } else {
      assert(_doneFuture != null && _doneFuture!._mayComplete);
      _doneFuture!._asyncComplete(null);
    }
  }
}

class _AsyncBroadcastStreamController<T> extends _BroadcastStreamController<T> {
  _AsyncBroadcastStreamController(void onListen()?, void onCancel()?)
    : super(onListen, onCancel);

  // EventDispatch interface.

  void _sendData(T data) {
    for (
      var subscription = _firstSubscription;
      subscription != null;
      subscription = subscription._next
    ) {
      subscription._addPending(_DelayedData<T>(data));
    }
  }

  void _sendError(Object error, StackTrace stackTrace) {
    for (
      var subscription = _firstSubscription;
      subscription != null;
      subscription = subscription._next
    ) {
      subscription._addPending(_DelayedError(error, stackTrace));
    }
  }

  void _sendDone() {
    if (!_isEmpty) {
      for (
        var subscription = _firstSubscription;
        subscription != null;
        subscription = subscription._next
      ) {
        subscription._addPending(const _DelayedDone());
      }
    } else {
      assert(_doneFuture != null && _doneFuture!._mayComplete);
      _doneFuture!._asyncComplete(null);
    }
  }
}

/// Stream controller that is used by [Stream.asBroadcastStream].
///
/// This stream controller allows incoming events while it is firing
/// other events. This is handled by delaying the events until the
/// current event is done firing, and then fire the pending events.
///
/// This class extends [_SyncBroadcastStreamController]. Events of
/// an "asBroadcastStream" stream are always initiated by events
/// on another stream, and it is fine to forward them synchronously.
class _AsBroadcastStreamController<T> extends _SyncBroadcastStreamController<T>
    implements _EventDispatch<T> {
  _PendingEvents<T>? _pending;

  _AsBroadcastStreamController(void onListen()?, void onCancel()?)
    : super(onListen, onCancel);

  bool get _hasPending {
    var pending = _pending;
    return pending != null && !pending.isEmpty;
  }

  void _addPendingEvent(_DelayedEvent event) {
    (_pending ??= _PendingEvents<T>()).add(event);
  }

  void add(T data) {
    if (!isClosed && _isFiring) {
      _addPendingEvent(_DelayedData<T>(data));
      return;
    }
    super.add(data);
    _flushPending();
  }

  void addError(Object error, [StackTrace? stackTrace]) {
    if (!_mayAddEvent) throw _addEventError();
    AsyncError(:error, :stackTrace) = _interceptUserError(error, stackTrace);
    if (!isClosed && _isFiring) {
      _addPendingEvent(_DelayedError(error, stackTrace));
      return;
    }
    _addError(error, stackTrace);
    _flushPending();
  }

  void _flushPending() {
    var pending = _pending;
    if (pending != null) {
      while (!pending.isEmpty) {
        pending.handleNext(this);
      }
    }
  }

  Future<void> close() {
    if (!isClosed && _isFiring) {
      _addPendingEvent(const _DelayedDone());
      _state |= _BroadcastStreamController._STATE_CLOSED;
      return super.done;
    }
    var result = super.close();
    assert(!_hasPending);
    return result;
  }

  void _callOnCancel() {
    var pending = _pending;
    if (pending != null) {
      pending.clear();
      _pending = null;
    }
    super._callOnCancel();
  }
}
