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

patch class _WindowsCodePageDecoder {
  /* patch */ static String _decodeBytes(List<int> bytes)
      native "SystemEncodingToString";
}


patch class _WindowsCodePageEncoder {
  /* patch */ static List<int> _encodeString(String string)
      native "StringToSystemEncoding";
}


patch class Process {
  /* patch */ static Future<Process> start(String executable,
                                           List<String> arguments,
                                           [ProcessOptions options]) {
    _ProcessImpl process = new _ProcessImpl(executable, arguments, options);
    return process._start();
  }

  /* patch */ static Future<ProcessResult> run(String executable,
                                               List<String> arguments,
                                               [ProcessOptions options]) {
    return new _NonInteractiveProcess(executable, arguments, options)._result;
  }
}


patch class _ProcessUtils {
  /* patch */ static _exit(int status) native "Process_Exit";
  /* patch */ static _setExitCode(int status) native "Process_SetExitCode";
}


class _ProcessStartStatus {
  int _errorCode;  // Set to OS error code if process start failed.
  String _errorMessage;  // Set to OS error message if process start failed.
}


class _ProcessImpl extends NativeFieldWrapperClass1 implements Process {
  _ProcessImpl(String path, List<String> arguments, ProcessOptions options) {
    if (path is !String) {
      throw new ArgumentError("Path is not a String: $path");
    }
    _path = path;

    if (arguments is !List) {
      throw new ArgumentError("Arguments is not a List: $arguments");
    }
    int len = arguments.length;
    _arguments = new List<String>.fixedLength(len);
    for (int i = 0; i < len; i++) {
      var arg = arguments[i];
      if (arg is !String) {
        throw new ArgumentError("Non-string argument: $arg");
      }
      _arguments[i] = arguments[i];
      if (Platform.operatingSystem == 'windows') {
        _arguments[i] = _windowsArgumentEscape(_arguments[i]);
      }
    }

    if (options != null && options.workingDirectory != null) {
      _workingDirectory = options.workingDirectory;
      if (_workingDirectory is !String) {
        throw new ArgumentError(
            "WorkingDirectory is not a String: $_workingDirectory");
      }
    }

    if (options != null && options.environment != null) {
      var env = options.environment;
      if (env is !Map) {
        throw new ArgumentError("Environment is not a map: $env");
      }
      _environment = [];
      env.forEach((key, value) {
        if (key is !String || value is !String) {
          throw new ArgumentError(
              "Environment key or value is not a string: ($key, $value)");
        }
        _environment.add('$key=$value');
      });
    }

    _in = new _Socket._internalReadOnly();  // stdout coming from process.
    _out = new _Socket._internalWriteOnly();  // stdin going to process.
    _err = new _Socket._internalReadOnly();  // stderr coming from process.
    _exitHandler = new _Socket._internalReadOnly();
    _ended = false;
    _started = false;
    _onExit = null;
  }

  String _windowsArgumentEscape(String argument) {
    var result = argument;
    if (argument.contains('\t') || argument.contains(' ')) {
      // Produce something that the C runtime on Windows will parse
      // back as this string.

      // Replace any number of '\' followed by '"' with
      // twice as many '\' followed by '\"'.
      var backslash = '\\'.charCodeAt(0);
      var sb = new StringBuffer();
      var nextPos = 0;
      var quotePos = argument.indexOf('"', nextPos);
      while (quotePos != -1) {
        var numBackslash = 0;
        var pos = quotePos - 1;
        while (pos >= 0 && argument.charCodeAt(pos) == backslash) {
          numBackslash++;
          pos--;
        }
        sb.add(argument.substring(nextPos, quotePos - numBackslash));
        for (var i = 0; i < numBackslash; i++) {
          sb.add(r'\\');
        }
        sb.add(r'\"');
        nextPos = quotePos + 1;
        quotePos = argument.indexOf('"', nextPos);
      }
      sb.add(argument.substring(nextPos, argument.length));
      result = sb.toString();

      // Add '"' at the beginning and end and replace all '\' at
      // the end with two '\'.
      sb = new StringBuffer('"');
      sb.add(result);
      nextPos = argument.length - 1;
      while (argument.charCodeAt(nextPos) == backslash) {
        sb.add('\\');
        nextPos--;
      }
      sb.add('"');
      result = sb.toString();
    }

    return result;
  }

  int _intFromBytes(List<int> bytes, int offset) {
    return (bytes[offset] +
            (bytes[offset + 1] << 8) +
            (bytes[offset + 2] << 16) +
            (bytes[offset + 3] << 24));
  }

  Future<Process> _start() {
    var completer = new Completer();
    // TODO(ager): Make the actual process starting really async instead of
    // simulating it with a timer.
    new Timer(0, (_) {
      var status = new _ProcessStartStatus();
      bool success = _startNative(_path,
                                  _arguments,
                                  _workingDirectory,
                                  _environment,
                                  _in,
                                  _out,
                                  _err,
                                  _exitHandler,
                                  status);
      if (!success) {
        _in.close();
        _out.close();
        _err.close();
        _exitHandler.close();
        completer.completeError(
            new ProcessException(_path,
                                 _arguments,
                                 status._errorMessage,
                                 status._errorCode));
        return;
      }
      _started = true;

      _in._closed = false;
      _out._closed = false;
      _err._closed = false;
      _exitHandler._closed = false;

      // Make sure to activate socket handlers now that the file
      // descriptors have been set.
      _in._activateHandlers();
      _out._activateHandlers();
      _err._activateHandlers();

      // Setup an exit handler to handle internal cleanup and possible
      // callback when a process terminates.
      int exitDataRead = 0;
      final int EXIT_DATA_SIZE = 8;
      List<int> exitDataBuffer = new List<int>.fixedLength(EXIT_DATA_SIZE);
      _exitHandler.inputStream.onData = () {

        int exitCode(List<int> ints) {
          var code = _intFromBytes(ints, 0);
          var negative = _intFromBytes(ints, 4);
          assert(negative == 0 || negative == 1);
          return (negative == 0) ? code : -code;
        }

        void handleExit() {
          _ended = true;
          _exitCode = exitCode(exitDataBuffer);
          if (_onExit != null) _onExit(_exitCode);
          _out.close();
        }

        exitDataRead += _exitHandler.inputStream.readInto(
            exitDataBuffer, exitDataRead, EXIT_DATA_SIZE - exitDataRead);
        if (exitDataRead == EXIT_DATA_SIZE) {
          _exitHandler.close();
          handleExit();
        }
      };

      completer.complete(this);
    });
    return completer.future;
  }

  bool _startNative(String path,
                    List<String> arguments,
                    String workingDirectory,
                    List<String> environment,
                    Socket input,
                    Socket output,
                    Socket error,
                    Socket exitHandler,
                    _ProcessStartStatus status) native "Process_Start";

  InputStream get stdout {
    return _in.inputStream;
  }

  InputStream get stderr {
    return _err.inputStream;
  }

  OutputStream get stdin {
    return _out.outputStream;
  }

  bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]) {
    if (signal is! ProcessSignal) {
      throw new ArgumentError(
          "Argument 'signal' must be a ProcessSignal");
    }
    assert(_started);
    if (_ended) return false;
    return _kill(this, signal._signalNumber);
  }

  bool _kill(Process p, int signal) native "Process_Kill";

  void set onExit(void callback(int exitCode)) {
    if (_ended) callback(_exitCode);
    _onExit = callback;
  }

  String _path;
  List<String> _arguments;
  String _workingDirectory;
  List<String> _environment;
  // Private methods of _Socket are used by _in, _out, and _err.
  _Socket _in;
  _Socket _out;
  _Socket _err;
  Socket _exitHandler;
  int _exitCode;
  bool _ended;
  bool _started;
  Function _onExit;
}


// _NonInteractiveProcess is a wrapper around an interactive process
// that buffers output so it can be delivered when the process exits.
// _NonInteractiveProcess is used to implement the Process.run
// method.
class _NonInteractiveProcess {
  _NonInteractiveProcess(String path,
                         List<String> arguments,
                         ProcessOptions options) {
    _completer = new Completer<ProcessResult>();
    // Extract output encoding options and verify arguments.
    var stdoutEncoding = Encoding.SYSTEM;
    var stderrEncoding = Encoding.SYSTEM;
    if (options != null) {
      if (options.stdoutEncoding != null) {
        stdoutEncoding = options.stdoutEncoding;
        if (stdoutEncoding is !Encoding) {
          throw new ArgumentError(
              'stdoutEncoding option is not an encoding: $stdoutEncoding');
        }
      }
      if (options.stderrEncoding != null) {
        stderrEncoding = options.stderrEncoding;
        if (stderrEncoding is !Encoding) {
          throw new ArgumentError(
              'stderrEncoding option is not an encoding: $stderrEncoding');
        }
      }
    }

    // Start the underlying process.
    var processFuture = new _ProcessImpl(path, arguments, options)._start();

    processFuture.then((Process p) {
      // Make sure the process stdin is closed.
      p.stdin.close();

      // Setup process exit handling.
      p.onExit = (exitCode) {
        _exitCode = exitCode;
        _checkDone();
      };

      // Setup stdout handling.
      _stdoutBuffer = new StringBuffer();
      var stdoutStream = new StringInputStream(p.stdout, stdoutEncoding);
      stdoutStream.onData = () {
        var data = stdoutStream.read();
        if (data != null) _stdoutBuffer.add(data);
      };
      stdoutStream.onClosed = () {
        _stdoutClosed = true;
        _checkDone();
      };

      // Setup stderr handling.
      _stderrBuffer = new StringBuffer();
      var stderrStream = new StringInputStream(p.stderr, stderrEncoding);
      stderrStream.onData = () {
        var data = stderrStream.read();
        if (data != null) _stderrBuffer.add(data);
      };
      stderrStream.onClosed = () {
        _stderrClosed = true;
        _checkDone();
      };
    }).catchError((error) {
      _completer.completeError(error.error);
    });
  }

  void _checkDone() {
    if (_exitCode != null && _stderrClosed && _stdoutClosed) {
      _completer.complete(new _ProcessResult(_exitCode,
                                             _stdoutBuffer.toString(),
                                             _stderrBuffer.toString()));
    }
  }

  Future<ProcessResult> get _result => _completer.future;

  Completer<ProcessResult> _completer;
  StringBuffer _stdoutBuffer;
  StringBuffer _stderrBuffer;
  int _exitCode;
  bool _stdoutClosed = false;
  bool _stderrClosed = false;
}


class _ProcessResult implements ProcessResult {
  const _ProcessResult(int this.exitCode,
                       String this.stdout,
                       String this.stderr);

  final int exitCode;
  final String stdout;
  final String stderr;
}
