// 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}) {
    assert(prefix != null);
    filter ??= (line) => [line];
    return stream
        .transform(utf8.decoder)
        .transform(const LineSplitter())
        .expand(filter)
        .listen((String line) {
      if (line != null) {
        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" && ');
    if (environment != null) {
      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;
  }
}
