// 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 "common_patch.dart";

@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: systemEncoding,
      Encoding stderrEncoding: systemEncoding}) {
    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: systemEncoding,
      Encoding stderrEncoding: systemEncoding}) {
    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<ProcessSignal> _controller;
  var _id;

  _SignalController(this.signal) {
    _controller = new StreamController<ProcessSignal>.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.watchSignal(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";
}

@pragma("vm:entry-point", "call")
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;
  }
}

@patch
class ProcessInfo {
  @patch
  static int get maxRss {
    var result = _maxRss();
    if (result is OSError) {
      throw result;
    }
    return result;
  }

  @patch
  static int get currentRss {
    var result = _currentRss();
    if (result is OSError) {
      throw result;
    }
    return result;
  }

  static _maxRss() native "ProcessInfo_MaxRSS";
  static _currentRss() native "ProcessInfo_CurrentRSS";
}

@pragma("vm:entry-point")
class _ProcessStartStatus {
  @pragma("vm:entry-point", "set")
  int _errorCode; // Set to OS error code if process start failed.
  @pragma("vm:entry-point", "set")
  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,
      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 (_modeHasStdio(mode)) {
      // stdin going to process.
      _stdin = new _StdSink(new _Socket._writePipe().._owner = this);
      // stdout coming from process.
      _stdout = new _StdStream(new _Socket._readPipe().._owner = this);
      // stderr coming from process.
      _stderr = new _StdStream(new _Socket._readPipe().._owner = this);
    }
    if (_modeIsAttached(mode)) {
      _exitHandler = new _Socket._readPipe();
    }
    _ended = false;
    _started = false;
  }

  _NativeSocket get _stdinNativeSocket =>
      (_stdin._sink as _Socket)._nativeSocket;
  _NativeSocket get _stdoutNativeSocket =>
      (_stdout._stream as _Socket)._nativeSocket;
  _NativeSocket get _stderrNativeSocket =>
      (_stderr._stream as _Socket)._nativeSocket;

  static bool _modeIsAttached(ProcessStartMode mode) {
    return (mode == ProcessStartMode.normal) ||
        (mode == ProcessStartMode.inheritStdio);
  }

  static bool _modeHasStdio(ProcessStartMode mode) {
    return (mode == ProcessStartMode.normal) ||
        (mode == ProcessStartMode.detachedWithStdio);
  }

  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<Process>();
    if (_modeIsAttached(_mode)) {
      _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(
          _Namespace._namespace,
          _path,
          _arguments,
          _workingDirectory,
          _environment,
          _mode._mode,
          _modeHasStdio(_mode) ? _stdinNativeSocket : null,
          _modeHasStdio(_mode) ? _stdoutNativeSocket : null,
          _modeHasStdio(_mode) ? _stderrNativeSocket : null,
          _modeIsAttached(_mode) ? _exitHandler._nativeSocket : null,
          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 (_modeIsAttached(_mode)) {
        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.
            if (_modeHasStdio(_mode)) {
              (_stdin._sink as _Socket).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(
        _Namespace._namespace,
        _path,
        _arguments,
        _workingDirectory,
        _environment,
        ProcessStartMode.normal._mode,
        _stdinNativeSocket,
        _stdoutNativeSocket,
        _stderrNativeSocket,
        _exitHandler._nativeSocket,
        status);
    if (!success) {
      throw new ProcessException(
          _path, _arguments, status._errorMessage, status._errorCode);
    }

    _resourceInfo = new _ProcessResourceInfo(this);

    var result = _wait(_stdinNativeSocket, _stdoutNativeSocket,
        _stderrNativeSocket, _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(
      _Namespace namespace,
      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);
}
