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

@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,
      {String workingDirectory,
       Map<String, String> environment,
       bool includeParentEnvironment: true,
       bool runInShell: false,
       ProcessStartMode mode: ProcessStartMode.NORMAL}) {
    _ProcessImpl process = new _ProcessImpl(executable,
                                            arguments,
                                            workingDirectory,
                                            environment,
                                            includeParentEnvironment,
                                            runInShell,
                                            mode);
    return process._start();
  }

  @patch static Future<ProcessResult> run(
      String executable,
      List<String> arguments,
      {String workingDirectory,
       Map<String, String> environment,
       bool includeParentEnvironment: true,
       bool runInShell: false,
       Encoding stdoutEncoding: SYSTEM_ENCODING,
       Encoding stderrEncoding: SYSTEM_ENCODING}) {
    return _runNonInteractiveProcess(executable,
                                     arguments,
                                     workingDirectory,
                                     environment,
                                     includeParentEnvironment,
                                     runInShell,
                                     stdoutEncoding,
                                     stderrEncoding);
  }

  @patch static ProcessResult runSync(
      String executable,
      List<String> arguments,
      {String workingDirectory,
       Map<String, String> environment,
       bool includeParentEnvironment: true,
       bool runInShell: false,
       Encoding stdoutEncoding: SYSTEM_ENCODING,
       Encoding stderrEncoding: SYSTEM_ENCODING}) {
    return _runNonInteractiveProcessSync(executable,
                                         arguments,
                                         workingDirectory,
                                         environment,
                                         includeParentEnvironment,
                                         runInShell,
                                         stdoutEncoding,
                                         stderrEncoding);
  }

  @patch static bool killPid(
      int pid, [ProcessSignal signal = ProcessSignal.SIGTERM]) {
    if (signal is! ProcessSignal) {
      throw new ArgumentError(
          "Argument 'signal' must be a ProcessSignal");
    }
    return _ProcessUtils._killPid(pid, signal._signalNumber);
  }
}


List<_SignalController> _signalControllers = new List(32);


class _SignalController {
  final ProcessSignal signal;

  StreamController _controller;
  var _id;

  _SignalController(this.signal) {
    _controller = new StreamController.broadcast(
        onListen: _listen,
        onCancel: _cancel);
  }

  Stream<ProcessSignal> get stream => _controller.stream;

  void _listen() {
    var id = _setSignalHandler(signal._signalNumber);
    if (id is! int) {
      _controller.addError(
          new SignalException("Failed to listen for $signal", id));
      return;
    }
    _id = id;
    var socket = new _RawSocket(new _NativeSocket.watch(id));
    socket.listen((event) {
      if (event == RawSocketEvent.READ) {
        var bytes = socket.read();
        for (int i = 0; i < bytes.length; i++) {
          _controller.add(signal);
        }
      }
    });
  }

  void _cancel() {
    if (_id != null) {
      _clearSignalHandler(signal._signalNumber);
      _id = null;
    }
  }

  static _setSignalHandler(int signal)
      native "Process_SetSignalHandler";
  static int _clearSignalHandler(int signal)
      native "Process_ClearSignalHandler";
}

Function _getWatchSignalInternal() => _ProcessUtils._watchSignalInternal;


@patch class _ProcessUtils {
  @patch static void _exit(int status) native "Process_Exit";
  @patch static void _setExitCode(int status)
      native "Process_SetExitCode";
  @patch static int _getExitCode() native "Process_GetExitCode";
  @patch static void _sleep(int millis) native "Process_Sleep";
  @patch static int _pid(Process process) native "Process_Pid";
  static bool _killPid(int pid, int signal)
      native "Process_KillPid";
  @patch static Stream<ProcessSignal> _watchSignal(ProcessSignal signal) {
    if (signal != ProcessSignal.SIGHUP &&
        signal != ProcessSignal.SIGINT &&
        signal != ProcessSignal.SIGTERM &&
        (Platform.isWindows ||
         (signal != ProcessSignal.SIGUSR1 &&
          signal != ProcessSignal.SIGUSR2 &&
          signal != ProcessSignal.SIGWINCH))) {
      throw new SignalException(
          "Listening for signal $signal is not supported");
    }
    return _watchSignalInternal(signal);
  }

  static Stream<ProcessSignal> _watchSignalInternal(ProcessSignal signal) {
    if (_signalControllers[signal._signalNumber] == null) {
      _signalControllers[signal._signalNumber] = new _SignalController(signal);
    }
    return _signalControllers[signal._signalNumber].stream;
  }
}


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


// The NativeFieldWrapperClass1 can not be used with a mixin, due to missing
// implicit constructor.
class _ProcessImplNativeWrapper extends NativeFieldWrapperClass1 {}

class _ProcessImpl extends _ProcessImplNativeWrapper implements Process {
  _ProcessResourceInfo _resourceInfo;
  static bool connectedResourceHandler = false;

  _ProcessImpl(String path,
               List<String> arguments,
               String this._workingDirectory,
               Map<String, String> environment,
               bool includeParentEnvironment,
               bool runInShell,
               ProcessStartMode mode) : super() {
    if (!connectedResourceHandler) {
      registerExtension('ext.dart.io.getProcesses',
                        _ProcessResourceInfo.getStartedProcesses);
      registerExtension('ext.dart.io.getProcessById',
                        _ProcessResourceInfo.getProcessInfoMapById);
      connectedResourceHandler = true;
    }

    if (runInShell) {
      arguments = _getShellArguments(path, arguments);
      path = _getShellCommand();
    }

    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>(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.isWindows) {
        _arguments[i] = _windowsArgumentEscape(_arguments[i]);
      }
    }

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

    _environment = [];
    // Ensure that we have a non-null environment.
    environment = (environment == null) ? (const {}) : environment;
    if (environment is !Map) {
      throw new ArgumentError("Environment is not a map: $environment");
    }
    environment.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');
    });
    if (includeParentEnvironment) {
      Platform.environment.forEach((key, value) {
        assert(key is String);
        assert(value is String);
        // Do not override keys already set as part of environment.
        if (!environment.containsKey(key)) {
          _environment.add('$key=$value');
        }
      });
    }

    if (mode is !ProcessStartMode) {
      throw new ArgumentError("Mode is not a ProcessStartMode: $mode");
    }
    _mode = mode;

    if (mode != ProcessStartMode.DETACHED) {
      // stdin going to process.
      _stdin = new _StdSink(new _Socket._writePipe());
      _stdin._sink._owner = this;
      // stdout coming from process.
      _stdout = new _StdStream(new _Socket._readPipe());
      _stdout._stream._owner = this;
      // stderr coming from process.
      _stderr = new _StdStream(new _Socket._readPipe());
      _stderr._stream._owner = this;
    }
    if (mode == ProcessStartMode.NORMAL) {
      _exitHandler = new _Socket._readPipe();
    }
    _ended = false;
    _started = false;
  }

  static String _getShellCommand() {
    if (Platform.isWindows) {
      return 'cmd.exe';
    }
    return '/bin/sh';
  }

  static List<String> _getShellArguments(String executable,
                                         List<String> arguments) {
    List<String> shellArguments = [];
    if (Platform.isWindows) {
      shellArguments.add('/c');
      shellArguments.add(executable);
      for (var arg in arguments) {
        shellArguments.add(arg);
      }
    } else {
      var commandLine = new StringBuffer();
      executable = executable.replaceAll("'", "'\"'\"'");
      commandLine.write("'$executable'");
      shellArguments.add("-c");
      for (var arg in arguments) {
        arg = arg.replaceAll("'", "'\"'\"'");
        commandLine.write(" '$arg'");
      }
      shellArguments.add(commandLine.toString());
    }
    return shellArguments;
  }

  String _windowsArgumentEscape(String argument) {
    var result = argument;
    if (argument.contains('\t') ||
        argument.contains(' ') ||
        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 = '\\'.codeUnitAt(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.codeUnitAt(pos) == backslash) {
          numBackslash++;
          pos--;
        }
        sb.write(argument.substring(nextPos, quotePos - numBackslash));
        for (var i = 0; i < numBackslash; i++) {
          sb.write(r'\\');
        }
        sb.write(r'\"');
        nextPos = quotePos + 1;
        quotePos = argument.indexOf('"', nextPos);
      }
      sb.write(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.write(result);
      nextPos = argument.length - 1;
      while (argument.codeUnitAt(nextPos) == backslash) {
        sb.write('\\');
        nextPos--;
      }
      sb.write('"');
      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();
    if (_mode == ProcessStartMode.NORMAL) {
      _exitCode = new Completer<int>();
    }
    // TODO(ager): Make the actual process starting really async instead of
    // simulating it with a timer.
    Timer.run(() {
      var status = new _ProcessStartStatus();
      bool success =
          _startNative(_path,
                       _arguments,
                       _workingDirectory,
                       _environment,
                       _mode.index,
                       _mode == ProcessStartMode.DETACHED
                           ? null : _stdin._sink._nativeSocket,
                       _mode == ProcessStartMode.DETACHED
                           ? null : _stdout._stream._nativeSocket,
                       _mode == ProcessStartMode.DETACHED
                           ? null : _stderr._stream._nativeSocket,
                       _mode != ProcessStartMode.NORMAL
                           ? null : _exitHandler._nativeSocket,
                       status);
      if (!success) {
        completer.completeError(
            new ProcessException(_path,
                                 _arguments,
                                 status._errorMessage,
                                 status._errorCode));
        return;
      }

      _started = true;
      _resourceInfo = new _ProcessResourceInfo(this);

      // Setup an exit handler to handle internal cleanup and possible
      // callback when a process terminates.
      if (_mode == ProcessStartMode.NORMAL) {
        int exitDataRead = 0;
        final int EXIT_DATA_SIZE = 8;
        List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE);
        _exitHandler.listen((data) {

          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.complete(exitCode(exitDataBuffer));
            // Kill stdin, helping hand if the user forgot to do it.
            _stdin._sink.destroy();
            _resourceInfo.stopped();
          }

          exitDataBuffer.setRange(
              exitDataRead, exitDataRead + data.length, data);
          exitDataRead += data.length;
          if (exitDataRead == EXIT_DATA_SIZE) {
            handleExit();
          }
        });
      }

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

  ProcessResult _runAndWait(Encoding stdoutEncoding,
                            Encoding stderrEncoding) {
    var status = new _ProcessStartStatus();
    _exitCode = new Completer<int>();
    bool success = _startNative(_path,
                                _arguments,
                                _workingDirectory,
                                _environment,
                                ProcessStartMode.NORMAL.index,
                                _stdin._sink._nativeSocket,
                                _stdout._stream._nativeSocket,
                                _stderr._stream._nativeSocket,
                                _exitHandler._nativeSocket,
                                status);
    if (!success) {
      throw new ProcessException(_path,
                                 _arguments,
                                 status._errorMessage,
                                 status._errorCode);
    }

    _resourceInfo = new _ProcessResourceInfo(this);

    var result = _wait(
        _stdin._sink._nativeSocket,
        _stdout._stream._nativeSocket,
        _stderr._stream._nativeSocket,
        _exitHandler._nativeSocket);

    getOutput(output, encoding) {
      if (encoding == null) return output;
      return encoding.decode(output);
    }

    _resourceInfo.stopped();

    return new ProcessResult(
        result[0],
        result[1],
        getOutput(result[2], stdoutEncoding),
        getOutput(result[3], stderrEncoding));
  }

  bool _startNative(String path,
                    List<String> arguments,
                    String workingDirectory,
                    List<String> environment,
                    int mode,
                    _NativeSocket stdin,
                    _NativeSocket stdout,
                    _NativeSocket stderr,
                    _NativeSocket exitHandler,
                    _ProcessStartStatus status) native "Process_Start";

  _wait(_NativeSocket stdin,
        _NativeSocket stdout,
        _NativeSocket stderr,
        _NativeSocket exitHandler) native "Process_Wait";

  Stream<List<int>> get stdout {
    return _stdout;
  }

  Stream<List<int>> get stderr {
    return _stderr;
  }

  IOSink get stdin {
    return _stdin;
  }

  Future<int> get exitCode => _exitCode != null ? _exitCode.future : null;

  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 _ProcessUtils._killPid(pid, signal._signalNumber);
  }

  int get pid => _ProcessUtils._pid(this);

  String _path;
  List<String> _arguments;
  String _workingDirectory;
  List<String> _environment;
  ProcessStartMode _mode;
  // Private methods of Socket are used by _in, _out, and _err.
  _StdSink _stdin;
  _StdStream _stdout;
  _StdStream _stderr;
  Socket _exitHandler;
  bool _ended;
  bool _started;
  Completer<int> _exitCode;
}


// _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.
Future<ProcessResult> _runNonInteractiveProcess(String path,
                                                List<String> arguments,
                                                String workingDirectory,
                                                Map<String, String> environment,
                                                bool includeParentEnvironment,
                                                bool runInShell,
                                                Encoding stdoutEncoding,
                                                Encoding stderrEncoding) {
  // Start the underlying process.
  return Process.start(path,
                       arguments,
                       workingDirectory: workingDirectory,
                       environment: environment,
                       includeParentEnvironment: includeParentEnvironment,
                       runInShell: runInShell).then((Process p) {
    int pid = p.pid;

    // Make sure the process stdin is closed.
    p.stdin.close();

    // Setup stdout and stderr handling.
    Future foldStream(Stream<List<int>> stream, Encoding encoding) {
      if (encoding == null) {
        return stream
            .fold(new BytesBuilder(), (builder, data) => builder..add(data))
            .then((builder) => builder.takeBytes());
      } else {
        return stream
            .transform(encoding.decoder)
            .fold(
                new StringBuffer(),
                (buf, data) {
                  buf.write(data);
                  return buf;
                })
            .then((sb) => sb.toString());
      }
    }

    Future stdout = foldStream(p.stdout, stdoutEncoding);
    Future stderr = foldStream(p.stderr, stderrEncoding);

    return Future.wait([p.exitCode, stdout, stderr]).then((result) {
      return new ProcessResult(pid, result[0], result[1], result[2]);
    });
  });
}

ProcessResult _runNonInteractiveProcessSync(
      String executable,
      List<String> arguments,
      String workingDirectory,
      Map<String, String> environment,
      bool includeParentEnvironment,
      bool runInShell,
      Encoding stdoutEncoding,
      Encoding stderrEncoding) {
  var process = new _ProcessImpl(executable,
                                 arguments,
                                 workingDirectory,
                                 environment,
                                 includeParentEnvironment,
                                 runInShell,
                                 ProcessStartMode.NORMAL);
  return process._runAndWait(stdoutEncoding, stderrEncoding);
}
