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

import 'package:meta/meta.dart';

import 'async_memoizer.dart';

/// An abstract class that implements [EventSink] in terms of [onData],
/// [onError], and [onClose] methods.
///
/// This takes care of ensuring that events can't be added after [close] is
/// called.
@Deprecated('Use EventSinkAdapter instead')
abstract class EventSinkBase<T> implements EventSink<T> {
  /// Whether [close] has been called and no more events may be written.
  bool get _closed => _closeMemo.hasRun;

  @override
  void add(T data) {
    _checkCanAddEvent();
    onAdd(data);
  }

  /// A method that handles data events that are passed to the sink.
  @visibleForOverriding
  void onAdd(T data);

  @override
  void addError(Object error, [StackTrace? stackTrace]) {
    _checkCanAddEvent();
    onError(error, stackTrace);
  }

  /// A method that handles error events that are passed to the sink.
  @visibleForOverriding
  void onError(Object error, [StackTrace? stackTrace]);

  @override
  Future<void> close() => _closeMemo.runOnce(onClose);
  final _closeMemo = AsyncMemoizer<void>();

  /// A method that handles the sink being closed.
  ///
  /// This may return a future that completes once the stream sink has shut
  /// down. If cleaning up can fail, the error may be reported in the returned
  /// future.
  @visibleForOverriding
  FutureOr<void> onClose();

  /// Asserts that the sink is in a state where adding an event is valid.
  void _checkCanAddEvent() {
    if (_closed) throw StateError('Cannot add event after closing');
  }
}

/// An abstract class that implements [StreamSink] in terms of [onData],
/// [onError], and [onClose] methods.
///
/// This takes care of ensuring that events can't be added after [close] is
/// called or during a call to [onStream].
@Deprecated('Use StreamSinkAdapter instead')
abstract class StreamSinkBase<T> extends EventSinkBase<T>
    implements StreamSink<T> {
  /// Whether a call to [addStream] is ongoing.
  bool _addingStream = false;

  @override
  Future<void> get done => _closeMemo.future;

  @override
  Future<void> addStream(Stream<T> stream) {
    _checkCanAddEvent();

    _addingStream = true;
    var completer = Completer<void>.sync();
    stream.listen(onAdd, onError: onError, onDone: () {
      _addingStream = false;
      completer.complete();
    });
    return completer.future;
  }

  @override
  Future<void> close() {
    if (_addingStream) throw StateError('StreamSink is bound to a stream');
    return super.close();
  }

  @override
  void _checkCanAddEvent() {
    super._checkCanAddEvent();
    if (_addingStream) throw StateError('StreamSink is bound to a stream');
  }
}

/// An abstract class that implements `dart:io`'s [IOSink]'s API in terms of
/// [onData], [onError], [onClose], and [onFlush] methods.
///
/// Because [IOSink] is defined in `dart:io`, this can't officially implement
/// it. However, it's designed to match its API exactly so that subclasses can
/// implement [IOSink] without any additional modifications.
///
/// This takes care of ensuring that events can't be added after [close] is
/// called or during a call to [onStream].
@Deprecated('Will be removed in version 2.9.0')
abstract class IOSinkBase extends StreamSinkBase<List<int>> {
  /// See [IOSink.encoding] from `dart:io`.
  Encoding encoding;

  IOSinkBase([this.encoding = utf8]);

  /// See [IOSink.flush] from `dart:io`.
  ///
  /// Because this base class doesn't do any buffering of its own, [flush]
  /// always completes immediately.
  ///
  /// Subclasses that do buffer events should override [flush] to complete once
  /// all events are delivered. They should also call `super.flush()` at the
  /// beginning of the method to throw a [StateError] if the sink is currently
  /// adding a stream.
  Future<void> flush() {
    if (_addingStream) throw StateError('StreamSink is bound to a stream');
    if (_closed) return Future.value();

    _addingStream = true;
    return onFlush().whenComplete(() {
      _addingStream = false;
    });
  }

  /// Flushes any buffered data to the underlying consumer, and returns a future
  /// that completes once the consumer has accepted all data.
  @visibleForOverriding
  Future<void> onFlush();

  /// See [IOSink.write] from `dart:io`.
  void write(Object? object) {
    var string = object.toString();
    if (string.isEmpty) return;
    add(encoding.encode(string));
  }

  /// See [IOSink.writeAll] from `dart:io`.
  void writeAll(Iterable<Object?> objects, [String separator = '']) {
    var first = true;
    for (var object in objects) {
      if (first) {
        first = false;
      } else {
        write(separator);
      }

      write(object);
    }
  }

  /// See [IOSink.writeln] from `dart:io`.
  void writeln([Object? object = '']) {
    write(object);
    write('\n');
  }

  /// See [IOSink.writeCharCode] from `dart:io`.
  void writeCharCode(int charCode) {
    write(String.fromCharCode(charCode));
  }
}
