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

// @dart = 2.5

part of dart.convert;

/// This class provides an interface for converters to
/// efficiently transmit String data.
///
/// Instead of limiting the interface to one non-chunked String it accepts
/// partial strings or can be transformed into a byte sink that
/// accepts UTF-8 code units.
///
/// This abstract class will likely get more methods over time. Implementers are
/// urged to extend [StringConversionSinkBase] or to mix in
/// [StringConversionSinkMixin], to ensure that their class covers the newly
/// added methods.
abstract class StringConversionSink extends ChunkedConversionSink<String> {
  StringConversionSink();
  factory StringConversionSink.withCallback(void callback(String accumulated)) =
      _StringCallbackSink;
  factory StringConversionSink.from(Sink<String> sink) = _StringAdapterSink;

  /// Creates a new instance wrapping the given [sink].
  ///
  /// Every string that is added to the returned instance is forwarded to
  /// the [sink]. The instance is allowed to buffer and is not required to
  /// forward immediately.
  factory StringConversionSink.fromStringSink(StringSink sink) =
      _StringSinkConversionSink<StringSink>;

  /// Adds the next [chunk] to `this`.
  ///
  /// Adds the substring defined by [start] and [end]-exclusive to `this`.
  ///
  /// If [isLast] is `true` closes `this`.
  void addSlice(String chunk, int start, int end, bool isLast);

  /// Returns `this` as a sink that accepts UTF-8 input.
  ///
  /// If used, this method must be the first and only call to `this`. It
  /// invalidates `this`. All further operations must be performed on the result.
  ByteConversionSink asUtf8Sink(bool allowMalformed);
  // - asRuneSink
  // - asCodeUnitsSink

  /// Returns `this` as a [ClosableStringSink].
  ///
  /// If used, this method must be the first and only call to `this`. It
  /// invalidates `this`. All further operations must be performed on the result.
  ClosableStringSink asStringSink();
}

/// A [ClosableStringSink] extends the [StringSink] interface by adding a
/// `close` method.
abstract class ClosableStringSink extends StringSink {
  /// Creates a new instance combining a [StringSink] [sink] and a callback
  /// [onClose] which is invoked when the returned instance is closed.
  factory ClosableStringSink.fromStringSink(StringSink sink, void onClose()) =
      _ClosableStringSink;

  /// Closes `this` and flushes any outstanding data.
  void close();
}

/// This class wraps an existing [StringSink] and invokes a
/// closure when [close] is invoked.
class _ClosableStringSink implements ClosableStringSink {
  final void Function() _callback;
  final StringSink _sink;

  _ClosableStringSink(this._sink, this._callback);

  void close() {
    _callback();
  }

  void writeCharCode(int charCode) {
    _sink.writeCharCode(charCode);
  }

  void write(Object o) {
    _sink.write(o);
  }

  void writeln([Object o = ""]) {
    _sink.writeln(o);
  }

  void writeAll(Iterable objects, [String separator = ""]) {
    _sink.writeAll(objects, separator);
  }
}

/// This class wraps an existing [StringConversionSink] and exposes a
/// [ClosableStringSink] interface. The wrapped sink only needs to implement
/// `add` and `close`.
// TODO(floitsch): make this class public?
class _StringConversionSinkAsStringSinkAdapter implements ClosableStringSink {
  static const _MIN_STRING_SIZE = 16;

  StringBuffer _buffer;
  StringConversionSink _chunkedSink;

  _StringConversionSinkAsStringSinkAdapter(this._chunkedSink)
      : _buffer = StringBuffer();

  void close() {
    if (_buffer.isNotEmpty) _flush();
    _chunkedSink.close();
  }

  void writeCharCode(int charCode) {
    _buffer.writeCharCode(charCode);
    if (_buffer.length > _MIN_STRING_SIZE) _flush();
  }

  void write(Object o) {
    if (_buffer.isNotEmpty) _flush();
    _chunkedSink.add(o.toString());
  }

  void writeln([Object o = ""]) {
    _buffer.writeln(o);
    if (_buffer.length > _MIN_STRING_SIZE) _flush();
  }

  void writeAll(Iterable objects, [String separator = ""]) {
    if (_buffer.isNotEmpty) _flush();
    var iterator = objects.iterator;
    if (!iterator.moveNext()) return;
    if (separator.isEmpty) {
      do {
        _chunkedSink.add(iterator.current.toString());
      } while (iterator.moveNext());
    } else {
      _chunkedSink.add(iterator.current.toString());
      while (iterator.moveNext()) {
        write(separator);
        _chunkedSink.add(iterator.current.toString());
      }
    }
  }

  void _flush() {
    var accumulated = _buffer.toString();
    _buffer.clear();
    _chunkedSink.add(accumulated);
  }
}

/// This class provides a base-class for converters that need to accept String
/// inputs.
abstract class StringConversionSinkBase extends StringConversionSinkMixin {}

/// This class provides a mixin for converters that need to accept String
/// inputs.
abstract class StringConversionSinkMixin implements StringConversionSink {
  void addSlice(String str, int start, int end, bool isLast);
  void close();

  void add(String str) {
    addSlice(str, 0, str.length, false);
  }

  ByteConversionSink asUtf8Sink(bool allowMalformed) {
    return _Utf8ConversionSink(this, allowMalformed);
  }

  ClosableStringSink asStringSink() {
    return _StringConversionSinkAsStringSinkAdapter(this);
  }
}

/// This class is a [StringConversionSink] that wraps a [StringSink].
class _StringSinkConversionSink<TStringSink extends StringSink>
    extends StringConversionSinkBase {
  TStringSink _stringSink;
  _StringSinkConversionSink(this._stringSink);

  void close() {}
  void addSlice(String str, int start, int end, bool isLast) {
    if (start != 0 || end != str.length) {
      for (var i = start; i < end; i++) {
        _stringSink.writeCharCode(str.codeUnitAt(i));
      }
    } else {
      _stringSink.write(str);
    }
    if (isLast) close();
  }

  void add(String str) {
    _stringSink.write(str);
  }

  ByteConversionSink asUtf8Sink(bool allowMalformed) {
    return _Utf8StringSinkAdapter(this, _stringSink, allowMalformed);
  }

  ClosableStringSink asStringSink() {
    return ClosableStringSink.fromStringSink(_stringSink, close);
  }
}

/// This class accumulates all chunks into one string
/// and invokes a callback when the sink is closed.
///
/// This class can be used to terminate a chunked conversion.
class _StringCallbackSink extends _StringSinkConversionSink<StringBuffer> {
  final void Function(String) _callback;
  _StringCallbackSink(this._callback) : super(StringBuffer());

  void close() {
    var accumulated = _stringSink.toString();
    _stringSink.clear();
    _callback(accumulated);
  }

  ByteConversionSink asUtf8Sink(bool allowMalformed) {
    return _Utf8StringSinkAdapter(this, _stringSink, allowMalformed);
  }
}

/// This class adapts a simple [ChunkedConversionSink] to a
/// [StringConversionSink].
///
/// All additional methods of the [StringConversionSink] (compared to the
/// ChunkedConversionSink) are redirected to the `add` method.
class _StringAdapterSink extends StringConversionSinkBase {
  final Sink<String> _sink;

  _StringAdapterSink(this._sink);

  void add(String str) {
    _sink.add(str);
  }

  void addSlice(String str, int start, int end, bool isLast) {
    if (start == 0 && end == str.length) {
      add(str);
    } else {
      add(str.substring(start, end));
    }
    if (isLast) close();
  }

  void close() {
    _sink.close();
  }
}

/// Decodes UTF-8 code units and stores them in a [StringSink].
class _Utf8StringSinkAdapter extends ByteConversionSink {
  final _Utf8Decoder _decoder;
  final Sink _sink;

  _Utf8StringSinkAdapter(this._sink, StringSink stringSink, bool allowMalformed)
      : _decoder = _Utf8Decoder(stringSink, allowMalformed);

  void close() {
    _decoder.close();
    if (_sink != null) _sink.close();
  }

  void add(List<int> chunk) {
    addSlice(chunk, 0, chunk.length, false);
  }

  void addSlice(
      List<int> codeUnits, int startIndex, int endIndex, bool isLast) {
    _decoder.convert(codeUnits, startIndex, endIndex);
    if (isLast) close();
  }
}

/// Decodes UTF-8 code units.
///
/// Forwards the decoded strings to the given [StringConversionSink].
// TODO(floitsch): make this class public?
class _Utf8ConversionSink extends ByteConversionSink {
  final _Utf8Decoder _decoder;
  final StringConversionSink _chunkedSink;
  final StringBuffer _buffer;
  _Utf8ConversionSink(StringConversionSink sink, bool allowMalformed)
      : this._(sink, StringBuffer(), allowMalformed);

  _Utf8ConversionSink._(
      this._chunkedSink, StringBuffer stringBuffer, bool allowMalformed)
      : _decoder = _Utf8Decoder(stringBuffer, allowMalformed),
        _buffer = stringBuffer;

  void close() {
    _decoder.close();
    if (_buffer.isNotEmpty) {
      var accumulated = _buffer.toString();
      _buffer.clear();
      _chunkedSink.addSlice(accumulated, 0, accumulated.length, true);
    } else {
      _chunkedSink.close();
    }
  }

  void add(List<int> chunk) {
    addSlice(chunk, 0, chunk.length, false);
  }

  void addSlice(List<int> chunk, int startIndex, int endIndex, bool isLast) {
    _decoder.convert(chunk, startIndex, endIndex);
    if (_buffer.isNotEmpty) {
      var accumulated = _buffer.toString();
      _chunkedSink.addSlice(accumulated, 0, accumulated.length, isLast);
      _buffer.clear();
      return;
    }
    if (isLast) close();
  }
}
