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

const int _STDIO_HANDLE_TYPE_TERMINAL = 0;
const int _STDIO_HANDLE_TYPE_PIPE = 1;
const int _STDIO_HANDLE_TYPE_FILE = 2;
const int _STDIO_HANDLE_TYPE_SOCKET = 3;
const int _STDIO_HANDLE_TYPE_OTHER = 4;


class _StdStream extends Stream<List<int>> {
  final Stream<List<int>> _stream;

  _StdStream(Stream<List<int>> this._stream);

  StreamSubscription<List<int>> listen(void onData(List<int> event),
                                       {void onError(error),
                                        void onDone(),
                                        bool cancelOnError}) {
    return _stream.listen(
        onData,
        onError: onError,
        onDone: onDone,
        cancelOnError: cancelOnError);
  }
}


class _StdinEventSink implements EventSink<String> {
  Function _add;
  Function _addError;
  Function _close;
  _StdinEventSink(this._add, this._addError, this._close);

  void add(String string) => _add(string);
  void addError(errorEvent) => _addError(errorEvent);
  void close() => _close();
}

/**
 * [Stdin] allows both synchronous and asynchronous reads from the standard
 * input stream.
 *
 * Mixing synchronous and asynchronous reads is undefined.
 */
class Stdin extends _StdStream implements Stream<List<int>> {
  Stdin._(Stream<List<int>> stream) : super(stream);

  /**
   * Synchronously read a line from stdin. This call will block until a full
   * line is available. The line will contain the newline character(s).
   *
   * If end-of-file is reached, `null` is returned.
   *
   * If end-of-file is reached after some data has already been read, that data
   * is returned.
   */
  String readLineSync({Encoding encoding: SYSTEM_ENCODING,
                       bool retainNewlines: false}) {
    const CR = 13;
    const LF = 10;
    var line = new StringBuffer();
    bool end = false;
    bool lastCharWasCR = false;
    var error;

    StreamController<List<int>> controller =
        new StreamController<List<int>>(sync: true);
    Stream stream = controller.stream.transform(encoding.decoder);
    stream.listen((String str) {
      line.write(str);
    }, onError: (e) {
      error = e;
    }, onDone: () {
      end = true;
    });

    bool empty = true;
    while (!end) {
      int b = readByteSync();

      if (b < 0) {
        // We didn't write the carriage return in case a line feed would be
        // the next character. Add it now.
        if (lastCharWasCR && !retainNewlines) controller.add([CR]);
        controller.close();
      } else {
        empty = false;
        // We consider \r\n and \n as new lines.
        // A \r on its own is treated like a normal character.

        if (b == CR) {
          if (lastCharWasCR && !retainNewlines) {
            // We didn't write the carriage return in case a line feed would be
            // the next character.
            // Add it now (since we treat it like a normal character now).
            controller.add([CR]);
          }
          // We add the carriage return only if we keep new lines.
          // Otherwise we need to wait for the next character (in case it is
          // a line feed).
          if (retainNewlines) controller.add([b]);
          lastCharWasCR = true;
        } else if (b == LF) {
          end = true;
          // We don't care if there was a carriage return before. If we keep
          // the line separators it has already been added to the controller.
          // Otherwise we don't want it anyway.
          if (retainNewlines) controller.add([b]);
          controller.close();
        } else {
          // Since the current character is not a line feed we flush the
          // carriage return we didn't write last iteration.
          if (lastCharWasCR) {
            controller.add([CR]);
            lastCharWasCR = false;
          }
          controller.add([b]);
        }
      }
      if (error != null) {
        // Error during decoding.
        throw error;
      }
    }

    if (empty) return null;
    return line.toString();
  }

  /**
   * Enable or disable echo mode on the [Stdin].
   *
   * If disabled, input from to console will not be echoed.
   *
   * Default depends on the parent process, but usually enabled.
   */
  external void set echoMode(bool enabled);

  /**
   * Enable or disable line mode on the [Stdin].
   *
   * If enabled, characters are delayed until a new-line character is entered.
   * If disabled, characters will be available as typed.
   *
   * Default depends on the parent process, but usually enabled.
   */
  external void set lineMode(bool enabled);

  /**
   * Synchronously read a byte from stdin. This call will block until a byte is
   * available.
   *
   * If at end of file, -1 is returned.
   */
  external int readByteSync();
}


class _StdSink implements IOSink {
  final IOSink _sink;

  _StdSink(IOSink this._sink);

  Encoding get encoding => _sink.encoding;
  void set encoding(Encoding encoding) {
    _sink.encoding = encoding;
  }
  void write(object) => _sink.write(object);
  void writeln([object = "" ]) => _sink.writeln(object);
  void writeAll(objects, [sep = ""]) => _sink.writeAll(objects, sep);
  void add(List<int> data) => _sink.add(data);
  void addError(error) => _sink.addError(error);
  void writeCharCode(int charCode) => _sink.writeCharCode(charCode);
  Future addStream(Stream<List<int>> stream) => _sink.addStream(stream);
  Future close() => _sink.close();
  Future get done => _sink.done;
}

class StdioType {
  static const StdioType TERMINAL = const StdioType._("terminal");
  static const StdioType PIPE = const StdioType._("pipe");
  static const StdioType FILE = const StdioType._("file");
  static const StdioType OTHER = const StdioType._("other");
  final String name;
  const StdioType._(String this.name);
  String toString() => "StdioType: $name";
}


Stdin _stdin;
IOSink _stdout;
IOSink _stderr;


Stdin get stdin {
  if (_stdin == null) {
    _stdin = _StdIOUtils._getStdioInputStream();
  }
  return _stdin;
}


IOSink get stdout {
  if (_stdout == null) {
    _stdout = _StdIOUtils._getStdioOutputStream(1);
  }
  return _stdout;
}


IOSink get stderr {
  if (_stderr == null) {
    _stderr = _StdIOUtils._getStdioOutputStream(2);
  }
  return _stderr;
}


StdioType stdioType(object) {
  if (object is _StdStream) {
    object = object._stream;
  } else if (object is _StdSink) {
    object = object._sink;
  }
  if (object is _FileStream) {
    return StdioType.FILE;
  }
  if (object is Socket) {
    switch (_StdIOUtils._socketType(object._nativeSocket)) {
      case _STDIO_HANDLE_TYPE_TERMINAL: return StdioType.TERMINAL;
      case _STDIO_HANDLE_TYPE_PIPE: return StdioType.PIPE;
      case _STDIO_HANDLE_TYPE_FILE:  return StdioType.FILE;
    }
  }
  if (object is IOSink) {
    try {
      if (object._target is _FileStreamConsumer) {
        return StdioType.FILE;
      }
    } catch (e) {
      // Only the interface implemented, _sink not available.
    }
  }
  return StdioType.OTHER;
}


class _StdIOUtils {
  external static IOSink _getStdioOutputStream(int fd);
  external static Stdin _getStdioInputStream();
  external static int _socketType(nativeSocket);
}
