// 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 _stdioHandleTypeTerminal = 0;
const int _stdioHandleTypePipe = 1;
const int _stdioHandleTypeFile = 2;
const int _stdioHandleTypeSocket = 3;
const int _stdioHandleTypeOther = 4;

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

  _StdStream(this._stream);

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

/**
 * [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>> {
  int _fd;

  Stdin._(Stream<List<int>> stream, this._fd) : super(stream);

  /**
   * Synchronously read a line from stdin. This call will block until a full
   * line is available.
   *
   * The argument [encoding] can be used to changed how the input should be
   * decoded. Default is [systemEncoding].
   *
   * If [retainNewlines] is `false`, the returned String will not contain the
   * final newline. If `true`, the returned String will contain the line
   * terminator. Default is `false`.
   *
   * If end-of-file is reached after any bytes have been read from stdin,
   * that data is returned.
   * Returns `null` if no bytes preceded the end of input.
   */
  String readLineSync(
      {Encoding encoding: systemEncoding, bool retainNewlines: false}) {
    const CR = 13;
    const LF = 10;
    final List<int> line = <int>[];
    // On Windows, if lineMode is disabled, only CR is received.
    bool crIsNewline = Platform.isWindows &&
        (stdioType(stdin) == StdioType.terminal) &&
        !lineMode;
    if (retainNewlines) {
      int byte;
      do {
        byte = readByteSync();
        if (byte < 0) {
          break;
        }
        line.add(byte);
      } while (byte != LF && !(byte == CR && crIsNewline));
      if (line.isEmpty) {
        return null;
      }
    } else if (crIsNewline) {
      // CR and LF are both line terminators, neither is retained.
      while (true) {
        int byte = readByteSync();
        if (byte < 0) {
          if (line.isEmpty) return null;
          break;
        }
        if (byte == LF || byte == CR) break;
        line.add(byte);
      }
    } else {
      // Case having to handle CR LF as a single unretained line terminator.
      outer:
      while (true) {
        int byte = readByteSync();
        if (byte == LF) break;
        if (byte == CR) {
          do {
            byte = readByteSync();
            if (byte == LF) break outer;

            line.add(CR);
          } while (byte == CR);
          // Fall through and handle non-CR character.
        }
        if (byte < 0) {
          if (line.isEmpty) return null;
          break;
        }
        line.add(byte);
      }
    }
    return encoding.decode(line);
  }

  /**
   * Check if echo mode is enabled on [stdin].
   */
  external bool get echoMode;

  /**
   * Enable or disable echo mode on [stdin].
   *
   * If disabled, input from to console will not be echoed.
   *
   * Default depends on the parent process, but usually enabled.
   *
   * On Windows this mode can only be enabled if [lineMode] is enabled as well.
   */
  external void set echoMode(bool enabled);

  /**
   * Check if line mode is enabled on [stdin].
   */
  external bool get lineMode;

  /**
   * Enable or disable line mode on [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.
   *
   * On Windows this mode can only be disabled if [echoMode] is disabled as well.
   */
  external void set lineMode(bool enabled);

  /**
    * Whether connected to a terminal that supports ANSI escape sequences.
    *
    * Not all terminals are recognized, and not all recognized terminals can
    * report whether they support ANSI escape sequences, so this value is a
    * best-effort attempt at detecting the support.
    *
    * The actual escape sequence support may differ between terminals,
    * with some terminals supporting more escape sequences than others,
    * and some terminals even differing in behavior for the same escape
    * sequence.
    *
    * The ANSI color selection is generally supported.
    *
    * Currently, a `TERM` environment variable containing the string `xterm`
    * will be taken as evidence that ANSI escape sequences are supported.
    * On Windows, only versions of Windows 10 after v.1511
    * ("TH2", OS build 10586) will be detected as supporting the output of
    * ANSI escape sequences, and only versions after v.1607 ("Anniversary
    * Update", OS build 14393) will be detected as supporting the input of
    * ANSI escape sequences.
    */
  external bool get supportsAnsiEscapes;

  /**
   * 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();

  /**
   * Returns true if there is a terminal attached to stdin.
   */
  bool get hasTerminal {
    try {
      return stdioType(this) == StdioType.terminal;
    } on FileSystemException catch (_) {
      // If stdioType throws a FileSystemException, then it is not hooked up to
      // a terminal, probably because it is closed, but let other exception
      // types bubble up.
      return false;
    }
  }
}

/**
 * [Stdout] represents the [IOSink] for either `stdout` or `stderr`.
 *
 * It provides a *blocking* `IOSink`, so using this to write will block until
 * the output is written.
 *
 * In some situations this blocking behavior is undesirable as it does not
 * provide the same non-blocking behavior as dart:io in general exposes.
 * Use the property [nonBlocking] to get an `IOSink` which has the non-blocking
 * behavior.
 *
 * This class can also be used to check whether `stdout` or `stderr` is
 * connected to a terminal and query some terminal properties.
 *
 * The [addError] API is inherited from  [StreamSink] and calling it will result
 * in an unhandled asynchronous error unless there is an error handler on
 * [done].
 */
class Stdout extends _StdSink implements IOSink {
  final int _fd;
  IOSink _nonBlocking;

  Stdout._(IOSink sink, this._fd) : super(sink);

  /**
   * Returns true if there is a terminal attached to stdout.
   */
  bool get hasTerminal => _hasTerminal(_fd);

  /**
   * Get the number of columns of the terminal.
   *
   * If no terminal is attached to stdout, a [StdoutException] is thrown. See
   * [hasTerminal] for more info.
   */
  int get terminalColumns => _terminalColumns(_fd);

  /*
   * Get the number of lines of the terminal.
   *
   * If no terminal is attached to stdout, a [StdoutException] is thrown. See
   * [hasTerminal] for more info.
   */
  int get terminalLines => _terminalLines(_fd);

  /**
    * Whether connected to a terminal that supports ANSI escape sequences.
    *
    * Not all terminals are recognized, and not all recognized terminals can
    * report whether they support ANSI escape sequences, so this value is a
    * best-effort attempt at detecting the support.
    *
    * The actual escape sequence support may differ between terminals,
    * with some terminals supporting more escape sequences than others,
    * and some terminals even differing in behavior for the same escape
    * sequence.
    *
    * The ANSI color selection is generally supported.
    *
    * Currently, a `TERM` environment variable containing the string `xterm`
    * will be taken as evidence that ANSI escape sequences are supported.
    * On Windows, only versions of Windows 10 after v.1511
    * ("TH2", OS build 10586) will be detected as supporting the output of
    * ANSI escape sequences, and only versions after v.1607 ("Anniversary
    * Update", OS build 14393) will be detected as supporting the input of
    * ANSI escape sequences.
    */
  bool get supportsAnsiEscapes => _supportsAnsiEscapes(_fd);

  external bool _hasTerminal(int fd);
  external int _terminalColumns(int fd);
  external int _terminalLines(int fd);
  external static bool _supportsAnsiEscapes(int fd);

  /**
   * Get a non-blocking `IOSink`.
   */
  IOSink get nonBlocking {
    if (_nonBlocking == null) {
      _nonBlocking = new IOSink(new _FileStreamConsumer.fromStdio(_fd));
    }
    return _nonBlocking;
  }
}

class StdoutException implements IOException {
  final String message;
  final OSError osError;

  const StdoutException(this.message, [this.osError]);

  String toString() {
    return "StdoutException: $message${osError == null ? "" : ", $osError"}";
  }
}

class StdinException implements IOException {
  final String message;
  final OSError osError;

  const StdinException(this.message, [this.osError]);

  String toString() {
    return "StdinException: $message${osError == null ? "" : ", $osError"}";
  }
}

class _StdConsumer implements StreamConsumer<List<int>> {
  final _file;

  _StdConsumer(int fd) : _file = _File._openStdioSync(fd);

  Future addStream(Stream<List<int>> stream) {
    var completer = new Completer();
    var sub;
    sub = stream.listen((data) {
      try {
        _file.writeFromSync(data);
      } catch (e, s) {
        sub.cancel();
        completer.completeError(e, s);
      }
    },
        onError: completer.completeError,
        onDone: completer.complete,
        cancelOnError: true);
    return completer.future;
  }

  Future close() {
    _file.closeSync();
    return new Future.value();
  }
}

class _StdSink implements IOSink {
  final IOSink _sink;

  _StdSink(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, [StackTrace stackTrace]) {
    _sink.addError(error, stackTrace);
  }

  void writeCharCode(int charCode) {
    _sink.writeCharCode(charCode);
  }

  Future addStream(Stream<List<int>> stream) => _sink.addStream(stream);
  Future flush() => _sink.flush();
  Future close() => _sink.close();
  Future get done => _sink.done;
}

/// The type of object a standard IO stream is attached to.
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");

  @Deprecated("Use terminal instead")
  static const StdioType TERMINAL = terminal;
  @Deprecated("Use pipe instead")
  static const StdioType PIPE = pipe;
  @Deprecated("Use file instead")
  static const StdioType FILE = file;
  @Deprecated("Use other instead")
  static const StdioType OTHER = other;

  final String name;
  const StdioType._(this.name);
  String toString() => "StdioType: $name";
}

Stdin _stdin;
Stdout _stdout;
Stdout _stderr;

// These may be set to different values by the embedder by calling
// _setStdioFDs when initializing dart:io.
int _stdinFD = 0;
int _stdoutFD = 1;
int _stderrFD = 2;

// This is an embedder entrypoint.
void _setStdioFDs(int stdin, int stdout, int stderr) {
  _stdinFD = stdin;
  _stdoutFD = stdout;
  _stderrFD = stderr;
}

/// The standard input stream of data read by this program.
Stdin get stdin {
  if (_stdin == null) {
    _stdin = _StdIOUtils._getStdioInputStream(_stdinFD);
  }
  return _stdin;
}

/// The standard output stream of data written by this program.
///
/// The `addError` API is inherited from  `StreamSink` and calling it will
/// result in an unhandled asynchronous error unless there is an error handler
/// on `done`.
Stdout get stdout {
  if (_stdout == null) {
    _stdout = _StdIOUtils._getStdioOutputStream(_stdoutFD);
  }
  return _stdout;
}

/// The standard output stream of errors written by this program.
///
/// The `addError` API is inherited from  `StreamSink` and calling it will
/// result in an unhandled asynchronous error unless there is an error handler
/// on `done`.
Stdout get stderr {
  if (_stderr == null) {
    _stderr = _StdIOUtils._getStdioOutputStream(_stderrFD);
  }
  return _stderr;
}

/// For a stream, returns whether it is attached to a file, pipe, terminal, or
/// something else.
StdioType stdioType(object) {
  if (object is _StdStream) {
    object = object._stream;
  } else if (object == stdout || object == stderr) {
    int stdiofd = object == stdout ? _stdoutFD : _stderrFD;
    switch (_StdIOUtils._getStdioHandleType(stdiofd)) {
      case _stdioHandleTypeTerminal:
        return StdioType.terminal;
      case _stdioHandleTypePipe:
        return StdioType.pipe;
      case _stdioHandleTypeFile:
        return StdioType.file;
    }
  }
  if (object is _FileStream) {
    return StdioType.file;
  }
  if (object is Socket) {
    int socketType = _StdIOUtils._socketType(object);
    if (socketType == null) return StdioType.other;
    switch (socketType) {
      case _stdioHandleTypeTerminal:
        return StdioType.terminal;
      case _stdioHandleTypePipe:
        return StdioType.pipe;
      case _stdioHandleTypeFile:
        return StdioType.file;
    }
  }
  if (object is _IOSinkImpl) {
    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 _getStdioOutputStream(int fd);
  external static Stdin _getStdioInputStream(int fd);

  /// Returns the socket type or `null` if [socket] is not a builtin socket.
  external static int _socketType(Socket socket);
  external static _getStdioHandleType(int fd);
}
