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

// TODO(jcollins-g): Merge this with similar utilities in dartdoc
// and extract into a separate package, generate testing and mirrors, and
// reimport that into the SDK, before cut and paste gets out of hand.

/// This is a modified version of dartdoc's
/// SubprocessLauncher from test/src/utils.dart, for use with the
/// nnbd_migration script.
import 'dart:convert';
import 'dart:io';

import 'multi_future_tracker.dart';

/// Maximum number of parallel subprocesses.  Use this to to avoid overloading
/// your CPU.
final MultiFutureTracker maxParallel =
    MultiFutureTracker(Platform.numberOfProcessors);

/// Route all executions of pub through this [MultiFutureTracker] to avoid
/// parallel executions of the pub command.
final MultiFutureTracker pubTracker = MultiFutureTracker(1);

final RegExp quotables = RegExp(r'[ "\r\n\$]');

/// SubprocessLauncher manages one or more launched, non-interactive
/// subprocesses.  It handles I/O streams, parses JSON output if
/// available, and logs debugging information so the user can see exactly
/// what was run.
class SubprocessLauncher {
  final String context;
  final Map<String, String> environmentDefaults;

  SubprocessLauncher(this.context, [Map<String, String>? environment])
      : environmentDefaults = environment ?? <String, String>{};

  /// Wraps [runStreamedImmediate] as a closure around
  /// [maxParallel.addFutureFromClosure].
  ///
  /// This essentially implements a 'make -j N' limit for all subcommands.
  Future<Iterable<Map>?> runStreamed(String executable, List<String> arguments,
      // TODO(jcollins-g): Fix primitive obsession: consolidate parameters into
      // another object.
      {String? workingDirectory,
      Map<String, String>? environment,
      bool includeParentEnvironment = true,
      void Function(String)? perLine,
      int retries = 0,
      String? instance,
      bool allowNonzeroExit = false}) async {
    // TODO(jcollins-g): The closure wrapping we've done has made it impossible
    // to catch exceptions when calling runStreamed.  Fix this.
    return maxParallel.runFutureFromClosure(() async {
      return retryClosure(
          () async => await runStreamedImmediate(executable, arguments,
              workingDirectory: workingDirectory,
              environment: environment,
              includeParentEnvironment: includeParentEnvironment,
              perLine: perLine,
              instance: instance,
              allowNonzeroExit: allowNonzeroExit),
          retries: retries);
    });
  }

  /// A wrapper around start/await process.exitCode that will display the
  /// output of the executable continuously and fail on non-zero exit codes.
  /// It will also parse any valid JSON objects (one per line) it encounters
  /// on stdout/stderr, and return them.  Returns null if no JSON objects
  /// were encountered, or if DRY_RUN is set to 1 in the execution environment.
  ///
  /// Makes running programs in grinder similar to set -ex for bash, even on
  /// Windows (though some of the bashisms will no longer make sense).
  /// TODO(jcollins-g): refactor to return a stream of stderr/stdout lines
  ///                   and their associated JSON objects.
  Future<Iterable<Map>?> runStreamedImmediate(
      String executable, List<String> arguments,
      {String? workingDirectory,
      Map<String, String>? environment,
      bool includeParentEnvironment = true,
      void Function(String)? perLine,
      // A tag added to [context] to construct the line prefix.
      // Use this to indicate the process or processes with the tag
      // share something in common, like a hostname, a package, or a
      // multi-step procedure.
      String? instance,
      bool allowNonzeroExit = false}) async {
    String prefix = context.isNotEmpty
        ? '$context${instance != null ? "-$instance" : ""}: '
        : '';

    environment ??= {};
    environment.addAll(environmentDefaults);
    List<Map>? jsonObjects;

    /// Parses json objects generated by the subprocess.  If a json object
    /// contains the key 'message' or the keys 'data' and 'text', return that
    /// value as a collection of lines suitable for printing.
    Iterable<String> jsonCallback(String line) {
      if (perLine != null) perLine(line);
      Map? result;
      try {
        result = json.decoder.convert(line) as Map?;
      } on FormatException {
        // ignore
      }
      if (result != null) {
        jsonObjects ??= [];
        jsonObjects!.add(result);
        if (result.containsKey('message')) {
          line = result['message'] as String;
        } else if (result.containsKey('data') &&
            result['data'] is Map &&
            (result['data'] as Map).containsKey('key')) {
          line = result['data']['text'] as String;
        }
      }
      return line.split('\n');
    }

    stderr.write('$prefix+ ');
    if (workingDirectory != null) stderr.write('(cd "$workingDirectory" && ');
    stderr.write(environment.keys.map((String key) {
      if (environment![key]!.contains(quotables)) {
        return "$key='${environment[key]}'";
      } else {
        return '$key=${environment[key]}';
      }
    }).join(' '));
    stderr.write(' ');
    stderr.write(executable);
    if (arguments.isNotEmpty) {
      for (String arg in arguments) {
        if (arg.contains(quotables)) {
          stderr.write(" '$arg'");
        } else {
          stderr.write(' $arg');
        }
      }
    }
    if (workingDirectory != null) stderr.write(')');
    stderr.write('\n');

    if (Platform.environment.containsKey('DRY_RUN')) return null;

    String realExecutable = executable;
    final List<String> realArguments = [];
    if (Platform.isLinux) {
      // Use GNU coreutils to force line buffering.  This makes sure that
      // subprocesses that die due to fatal signals do not chop off the
      // last few lines of their output.
      //
      // Dart does not actually do this (seems to flush manually) unless
      // the VM crashes.
      realExecutable = 'stdbuf';
      realArguments.addAll(['-o', 'L', '-e', 'L']);
      realArguments.add(executable);
    }
    realArguments.addAll(arguments);

    Process process = await Process.start(realExecutable, realArguments,
        workingDirectory: workingDirectory,
        environment: environment,
        includeParentEnvironment: includeParentEnvironment);
    Future<void> stdoutFuture = _printStream(process.stdout, stdout,
        prefix: prefix, filter: jsonCallback);
    Future<void> stderrFuture = _printStream(process.stderr, stderr,
        prefix: prefix, filter: jsonCallback);
    await Future.wait([stderrFuture, stdoutFuture, process.exitCode]);

    int exitCode = await process.exitCode;
    if (exitCode != 0 && !allowNonzeroExit) {
      throw ProcessException(executable, arguments,
          'SubprocessLauncher got non-zero exitCode: $exitCode', exitCode);
    }
    return jsonObjects;
  }

  /// From flutter:dev/tools/dartdoc.dart, modified.
  static Future<void> _printStream(Stream<List<int>> stream, Stdout output,
      {String prefix = '', Iterable<String> Function(String line)? filter}) {
    filter ??= (line) => [line];
    return stream
        .transform(utf8.decoder)
        .transform(const LineSplitter())
        .expand(filter)
        .listen((String line) {
      output.write('$prefix$line'.trim());
      output.write('\n');
    }).asFuture();
  }
}
