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

// Casting wrappers for asynchronous classes.

class CastStream<S, T> extends Stream<T> {
  final Stream<S> _source;
  CastStream(this._source);
  bool get isBroadcast => _source.isBroadcast;

  StreamSubscription<T> listen(
    void Function(T data)? onData, {
    Function? onError,
    void Function()? onDone,
    bool? cancelOnError,
  }) {
    return new CastStreamSubscription<S, T>(
        _source.listen(null, onDone: onDone, cancelOnError: cancelOnError),
      )
      ..onData(onData)
      ..onError(onError);
  }

  Stream<R> cast<R>() => new CastStream<S, R>(_source);
}

class CastStreamSubscription<S, T> implements StreamSubscription<T> {
  final StreamSubscription<S> _source;

  /// Zone where listen was called.
  final Zone _zone = Zone.current;

  /// User's data handler.
  void Function(T)? _handleData;

  /// Copy of _source's handleError so we can report errors in onData.
  Function? _handleError;

  CastStreamSubscription(this._source) {
    _source.onData(_onData);
  }

  Future cancel() => _source.cancel();

  void onData(void Function(T data)? handleData) {
    _handleData =
        handleData == null
            ? null
            : _zone.registerUnaryCallback<dynamic, T>(handleData);
  }

  void onError(Function? handleError) {
    _source.onError(handleError);
    if (handleError == null) {
      _handleError = null;
    } else if (handleError is void Function(Object, StackTrace)) {
      _handleError = _zone.registerBinaryCallback<dynamic, Object, StackTrace>(
        handleError,
      );
    } else if (handleError is void Function(Object)) {
      _handleError = _zone.registerUnaryCallback<dynamic, Object>(handleError);
    } else {
      throw ArgumentError(
        "handleError callback must take either an Object "
        "(the error), or both an Object (the error) and a StackTrace.",
      );
    }
  }

  void onDone(void handleDone()?) {
    _source.onDone(handleDone);
  }

  void _onData(S data) {
    if (_handleData == null) return;
    T targetData;
    try {
      targetData = data as T;
    } catch (error, stack) {
      var handleError = _handleError;
      if (handleError == null) {
        _zone.handleUncaughtError(error, stack);
      } else if (handleError is void Function(Object, StackTrace)) {
        _zone.runBinaryGuarded<Object, StackTrace>(handleError, error, stack);
      } else {
        _zone.runUnaryGuarded<Object>(
          handleError as void Function(Object),
          error,
        );
      }
      return;
    }
    _zone.runUnaryGuarded(_handleData!, targetData);
  }

  void pause([Future? resumeSignal]) {
    _source.pause(resumeSignal);
  }

  void resume() {
    _source.resume();
  }

  bool get isPaused => _source.isPaused;

  Future<E> asFuture<E>([E? futureValue]) => _source.asFuture<E>(futureValue);
}

class CastStreamTransformer<SS, ST, TS, TT>
    extends StreamTransformerBase<TS, TT> {
  final StreamTransformer<SS, ST> _source;
  CastStreamTransformer(this._source);

  StreamTransformer<RS, RT> cast<RS, RT>() =>
      new CastStreamTransformer<SS, ST, RS, RT>(_source);
  Stream<TT> bind(Stream<TS> stream) =>
      _source.bind(stream.cast<SS>()).cast<TT>();
}

class CastConverter<SS, ST, TS, TT> extends Converter<TS, TT> {
  final Converter<SS, ST> _source;
  CastConverter(this._source);

  TT convert(TS input) => _source.convert(input as SS) as TT;

  // cast is inherited from Converter.

  Stream<TT> bind(Stream<TS> stream) =>
      _source.bind(stream.cast<SS>()).cast<TT>();

  Converter<RS, RT> cast<RS, RT>() =>
      new CastConverter<SS, ST, RS, RT>(_source);
}
