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

/**
 * Basic input stream which supplies binary data.
 *
 * Input streams are used to read data sequentially from some data
 * source. All input streams are non-blocking. They each have a number
 * of read calls which will always return without any IO related
 * blocking. If the requested data is not available a read call will
 * return `null`. All input streams have one or more handlers which
 * will trigger when data is available.
 *
 * The following example shows a data handler in an ordinary input
 * stream which will be called when some data is available and a call
 * to read will not return `null`.
 *
 *     InputStream input = ...
 *     input.onData = () {
 *       var data = input.read();
 *       ...
 *     };
 *
 * If for some reason the data from an input stream cannot be handled
 * by the application immediately setting the data handler to `null`
 * will avoid further callbacks until it is set to a function
 * again. While the data handler is not active system flow control
 * will be used to avoid buffering more data than needed.
 *
 * Always set up appropriate handlers when using input streams.
 *
 */
abstract class InputStream {
  /**
   * Reads data from the stream. Returns a system allocated buffer
   * with up to [len] bytes. If no value is passed for [len] all
   * available data will be returned. If no data is available null will
   * be returned.
   */
  List<int> read([int len]);

  /**
   * Reads up to [len] bytes into buffer [buffer] starting at offset
   * [offset]. Returns the number of bytes actually read which might
   * be zero. If [offset] is not specified 0 is used. If [len] is not
   * specified the length of [buffer] is used.
   */
  int readInto(List<int> buffer, [int offset, int len]);

  /**
   * Returns the number of bytes available for immediate reading.
   */
  int available();

  /**
   * Pipe the content of this input stream directly to the output
   * stream [output]. The default behavior is to close the output when
   * all the data from the input stream have been written. Specifying
   * `false` for the optional argument [close] keeps the output
   * stream open after writing all data from the input stream.
   */
  void pipe(OutputStream output, [bool close = true]);

  /**
   * Close the underlying communication channel to avoid getting any
   * more data. In normal situations, where all data is read from the
   * stream until the close handler is called, calling [close] is not
   * required. When [close] is used the close handler will still be
   * called.
   */
  void close();

  /**
   * Returns whether the stream is closed. There will be no more data
   * to read.
   */
  bool get closed;

  /**
   * Sets the handler that gets called when data is available.
   */
  void set onData(void callback());

  /**
   * Sets the handler that gets called when there will be no more data
   * available in the stream.
   */
  void set onClosed(void callback());

  /**
   * Sets the handler that gets called when the underlying
   * communication channel gets into some kind of error situation.
   */
  void set onError(void callback(e));
}


/**
 * String encodings.
 */
class Encoding {
  static const Encoding UTF_8 = const Encoding._internal("UTF-8");
  static const Encoding ISO_8859_1 = const Encoding._internal("ISO-8859-1");
  static const Encoding ASCII = const Encoding._internal("ASCII");
  const Encoding._internal(String this.name);
  final String name;
}


/**
 * A string input stream wraps a basic input stream and supplies
 * string data. This data can be read either as string chunks or as
 * lines separated by line termination character sequences.
 */
abstract class StringInputStream {
  /**
   * Decodes a binary input stream into characters using the specified
   * encoding.
   */
  factory StringInputStream(InputStream input,
                            [Encoding encoding = Encoding.UTF_8]) {
    return new _StringInputStream(input, encoding);
  }

  /**
   * Reads up to [len] characters from the stream. if [len] is not
   * specified reads as many characters as is available from the
   * stream. If no data is available null will be returned.
   */
  String read([int len]);

  /**
   * Reads the next line from the stream. The line ending characters
   * will not be part of the returned string. If a full line is not
   * available null will be returned.
   */
  String readLine();

  /**
   * Returns the number of characters available for immediate
   * reading. Note that this includes all characters that will be in
   * the String returned from [read] this includes line breaking
   * characters. If [readLine] is used for reading one can observe
   * less characters being returned as the line breaking characters
   * are discarded.
   */
  int available();

  /**
   * Returns whether the stream has been closed. There might still be
   * more data to read.
   */
  bool get closed;

  /**
   * Returns the encoding used to decode the binary data into characters.
   */
  Encoding get encoding;

  /**
   * Sets the handler that gets called when data is available. The two
   * handlers [onData] and [onLine] are mutually exclusive
   * and setting one will remove the other.
   */
  void set onData(void callback());

  /**
   * Sets the handler that gets called when a line is available. The
   * two handlers [onData] and [onLine] are mutually
   * exclusive and setting one will remove the other.
   */
  void set onLine(void callback());

  /**
   * Sets the handler that gets called when there will be no more data
   * available in the stream.
   */
  void set onClosed(void callback());

  /**
   * Sets the handler that gets called when the underlying
   * communication channel gets into some kind of error situation.
   */
  void set onError(void callback(e));
}


/**
 * A chunked input stream wraps a basic input stream and supplies
 * binary data in configurable chunk sizes.
 */
abstract class ChunkedInputStream {
  /**
   * Adds buffering to an input stream and provide the ability to read
   * the data in known size chunks.
   */
  factory ChunkedInputStream(InputStream input, [int chunkSize = 0]) {
    return new _ChunkedInputStream(input, chunkSize);
  }

  /**
   * Reads [chunkSize] bytes from the stream. If [chunkSize] bytes are
   * not currently available null is returned. When the stream is
   * closed the last call can return with less than [chunkSize] bytes.
   */
  List<int> read();

  /**
   * Returns whether the stream has been closed. There might still be
   * more data to read.
   */
  bool get closed;

  /**
   * Returns the chunk size used by this stream.
   */
  int get chunkSize;

  /**
   * Sets the chunk size used by this stream.
   */
  void set chunkSize(int chunkSize);

  /**
   * Sets the handler that gets called when at least [chunkSize] bytes
   * of data is available or the underlying stream has been closed and
   * there is still unread data.
   */
  void set onData(void callback());

  /**
   * Sets the handler that gets called when there will be no more data
   * available in the stream.
   */
  void set onClosed(void callback());

  /**
   * Sets the handler that gets called when the underlying
   * communication channel gets into some kind of error situation.
   */
  void set onError(void callback(e));
}


class StreamException implements Exception {
  const StreamException([String this.message = ""]);
  const StreamException.streamClosed() : message = "Stream closed";
  String toString() => "StreamException: $message";
  final String message;
}
