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

  /**
   * 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 = new 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();
    Iterator 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() {
    String 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 new _Utf8ConversionSink(this, allowMalformed);
  }

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

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

  void close() {}
  void addSlice(String str, int start, int end, bool isLast) {
    if (start != 0 || end != str.length) {
      for (int 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 new _Utf8StringSinkAdapter(this, _stringSink, allowMalformed);
  }

  ClosableStringSink asStringSink() {
    return new ClosableStringSink.fromStringSink(_stringSink, this.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 {
  final _ChunkedConversionCallback<String> _callback;
  _StringCallbackSink(this._callback) : super(new StringBuffer());

  void close() {
    StringBuffer buffer = _stringSink;
    String accumulated = buffer.toString();
    buffer.clear();
    _callback(accumulated);
  }

  ByteConversionSink asUtf8Sink(bool allowMalformed) {
    return new _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 = new _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, new StringBuffer(), allowMalformed);

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

  void close() {
    _decoder.close();
    if (_buffer.isNotEmpty) {
      String 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) {
      String accumulated = _buffer.toString();
      _chunkedSink.addSlice(accumulated, 0, accumulated.length, isLast);
      _buffer.clear();
      return;
    }
    if (isLast) close();
  }
}
