// 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();
    String str = o.toString();
    _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();
  }
}
