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

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();
}

typedef void _StringSinkCloseCallback();

/// This class wraps an existing [StringSink] and invokes a
/// closure when [close] is invoked.
class _ClosableStringSink implements ClosableStringSink {
  final _StringSinkCloseCallback _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 _ChunkedConversionCallback<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();
  }
}
