// Copyright (c) 2020, 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.

import 'dart:io';
import 'dart:isolate';

/// Contains methods used to communicate DartDev results back to the VM.
///
/// Messages are received in runtime/bin/dartdev_isolate.cc.
abstract class VmInteropHandler {
  /// Initializes [VmInteropHandler] to utilize [port] to communicate with the
  /// VM.
  static void initialize(SendPort? port) => _port = port;

  /// Notifies the VM to run [script] with [args] upon DartDev exit.
  ///
  /// If [packageConfigOverride] is given, that is where the packageConfig is found.
  ///
  /// If [markMainIsolateAsSystemIsolate] is given and set to true, the spawned
  /// isolate will run with `--mark-main-isolate-as-system-isolate` enabled.
  ///
  /// If [useExecProcess] is given and set to true, the script is executed by
  /// execing it (On Linux/Mac the exec call is used, on Windows a new child
  /// process is started).
  static void run(
    String script,
    List<String> args, {
    String? packageConfigOverride,
    // TODO(bkonyi): remove once DartDev moves to AOT and this flag can be
    // provided directly to the process spawned by `dart run` and `dart test`.
    //
    // See https://github.com/dart-lang/sdk/issues/53576
    bool markMainIsolateAsSystemIsolate = false,
    bool useExecProcess = false,
  }) {
    List<String> argsList;
    if (useExecProcess && Platform.isWindows) {
      // On Windows if a new process is used to execute the script we
      // need to escape the script path and all the arguments as we
      // construct a single command line string to be passed to the
      // Windows process create call.
      if (script.contains(' ') && !script.contains('"')) {
        // Escape paths that may contain spaces
        script = '"$script"';
      }
      argsList = [
        for (int i = 0; i < args.length; i++) _windowsArgumentEscape(args[i]),
      ];
    } else {
      // Copy the list so it doesn't get GC'd underneath us.
      argsList = args.toList();
    }
    final port = _port;
    if (port == null) return;
    final message = <dynamic>[
      useExecProcess ? _kResultRunExec : _kResultRun,
      script,
      packageConfigOverride,
      markMainIsolateAsSystemIsolate,
      argsList
    ];
    port.send(message);
  }

  /// Notifies the VM that DartDev has completed running. If provided a
  /// non-zero [exitCode], the VM will terminate with the given exit code.
  static void exit(int? exitCode) {
    final port = _port;
    if (port == null) return;
    final message = <dynamic>[_kResultExit, exitCode];
    port.send(message);
  }

  /// This code is identical to the one in process_patch.dart, please ensure
  /// changes made here are also done in process_patch.dart.
  /// TODO : figure out if this functionality can be abstracted out to a
  ///        common place.
  static String _windowsArgumentEscape(String argument) {
    if (argument.isEmpty) {
      return '""';
    }
    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 = 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 = StringBuffer('"');
      sb.write(result);
      nextPos = argument.length - 1;
      while (argument.codeUnitAt(nextPos) == backslash) {
        sb.write('\\');
        nextPos--;
      }
      sb.write('"');
      result = sb.toString();
    }

    return result;
  }

  // Note: keep in sync with runtime/bin/dartdev_isolate.h
  static const int _kResultRun = 1;
  static const int _kResultRunExec = 2;
  static const int _kResultExit = 3;

  static SendPort? _port;
}
