// 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,
       bool detach: false}) {
    _ProcessImpl process = new _ProcessImpl(executable,
                                            arguments,
                                            workingDirectory,
                                            environment,
                                            includeParentEnvironment,
                                            runInShell,
                                            detach);
    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);
  }
}


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;
    }
  }

  /* patch */ static _setSignalHandler(int signal)
      native "Process_SetSignalHandler";
  /* patch */ 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";
  /* 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 with _ServiceObject
    implements Process {
  // Use default Map so we keep order.
  static Map<int, _ProcessImpl> _processes = new Map<int, _ProcessImpl>();

  _ProcessImpl(String path,
               List<String> arguments,
               String this._workingDirectory,
               Map<String, String> environment,
               bool includeParentEnvironment,
               bool runInShell,
               bool detach) : super() {
    _processes[_serviceId] = this;
    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 (detach is !bool) {
      throw new ArgumentError("Detach is not a boolean: $detach");
    }
    _detach = detach;


    if (!detach) {
      // 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;
      _exitHandler = new _Socket._readPipe();
    }
    _ended = false;
    _started = false;
  }

  String get _serviceTypePath => 'io/processes';
  String get _serviceTypeName => 'Process';

  Map _toJSON(bool ref) {
    var r = {
      'id': _servicePath,
      'type': _serviceType(ref),
      'name': '$_path',
      'user_name': '$_path',
      'pid': '$pid',
      'arguments': _arguments.join(' '),
    };
    if (ref) {
      return r;
    }
    r['started'] = _started;
    r['ended'] = _ended;
    r['path'] = _path;
    r['environment'] = _environment;
    r['workingDirectory'] = _workingDirectory == null ? '.' : _workingDirectory;
    if (_stdin._sink._nativeSocket.owner != null) {
      r['stdin'] = _stdin._sink._nativeSocket._toJSON(true);
    }
    if (_stdout._stream._nativeSocket.owner != null) {
      r['stdout'] = _stdout._stream._nativeSocket._toJSON(true);
    }
    if (_stderr._stream._nativeSocket.owner != null) {
      r['stderr'] = _stderr._stream._nativeSocket._toJSON(true);
    }
    return r;
  }

  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 (!_detach) {
      _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,
                       _detach,
                       _detach ? null : _stdin._sink._nativeSocket,
                       _detach ? null : _stdout._stream._nativeSocket,
                       _detach ? null : _stderr._stream._nativeSocket,
                       _detach ? null : _exitHandler._nativeSocket,
                       status);
      if (!success) {
        completer.completeError(
            new ProcessException(_path,
                                 _arguments,
                                 status._errorMessage,
                                 status._errorCode));
        return;
      }

      _started = true;

      // Setup an exit handler to handle internal cleanup and possible
      // callback when a process terminates.
      if (!_detach) {
        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();
            _processes.remove(_serviceId);
          }

          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,
                                false,
                                _stdin._sink._nativeSocket,
                                _stdout._stream._nativeSocket,
                                _stderr._stream._nativeSocket,
                                _exitHandler._nativeSocket,
                                status);
    if (!success) {
      throw new ProcessException(_path,
                                 _arguments,
                                 status._errorMessage,
                                 status._errorCode);
    }

    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);
    }

    _processes.remove(_serviceId);

    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,
                    bool detach,
                    _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 _kill(this, signal._signalNumber);
  }

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

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

  String _path;
  List<String> _arguments;
  String _workingDirectory;
  List<String> _environment;
  bool _detach;
  // 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,
                                 false);
  return process._runAndWait(stdoutEncoding, stderrEncoding);
}


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

  final int pid;
  final int exitCode;
  final stdout;
  final stderr;
}
