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

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

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