// Copyright 2020 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This example shows how to send a bunch of jobs to ProcessPool for processing.
//
// This example program is actually pretty useful even if you don't use
// process_runner for your Dart project. It can speed up processing of a bunch
// of single-threaded CPU-intensive commands by a multiple of the number of
// processor cores you have (modulo being disk/network bound, of course).

import 'dart:io';

import 'package:args/args.dart';
import 'package:process_runner/process_runner.dart';

const String _kHelpFlag = 'help';
const String _kQuietFlag = 'quiet';
const String _kReportFlag = 'report';
const String _kPrintStdoutFlag = 'stdout';
const String _kPrintStderrFlag = 'stderr';
const String _kRunInShellFlag = 'run-in-shell';
const String _kAllowFailureFlag = 'fail-ok';
const List<String> _kFlags = <String>[
  _kHelpFlag,
  _kQuietFlag,
  _kReportFlag,
  _kPrintStdoutFlag,
  _kPrintStderrFlag,
  _kRunInShellFlag,
];
const String _kJobsOption = 'jobs';
const String _kWorkingDirectoryOption = 'working-directory';
const String _kCommandOption = 'command';
const String _kSourceOption = 'source';
const String _kGroupOption = 'group';
const String _kAppName = 'process_runner';

// This only works for escaped spaces and things in double or single quotes.
// This is just an example, modify to meet your own requirements.
List<String> splitIntoArgs(String args) {
  bool inQuote = false;
  bool inEscape = false;
  String quoteMatch = '';
  final List<String> result = <String>[];
  final List<String> currentArg = <String>[];
  for (int i = 0; i < args.length; ++i) {
    final String char = args[i];
    if (inEscape) {
      switch (char) {
        case 'n':
          currentArg.add('\n');
          break;
        case 't':
          currentArg.add('\t');
          break;
        case 'r':
          currentArg.add('\r');
          break;
        case 'b':
          currentArg.add('\b');
          break;
        default:
          currentArg.add(char);
          break;
      }
      inEscape = false;
      continue;
    }
    if (char == ' ' && !inQuote) {
      result.add(currentArg.join(''));
      currentArg.clear();
      continue;
    }
    if (char == r'\') {
      inEscape = true;
      continue;
    }
    if (inQuote) {
      if (char == quoteMatch) {
        inQuote = false;
        quoteMatch = '';
      } else {
        currentArg.add(char);
      }
      continue;
    }
    if (char == '"' || char == '"') {
      inQuote = !inQuote;
      quoteMatch = args[i];
      continue;
    }
    currentArg.add(char);
  }
  if (currentArg.isNotEmpty) {
    result.add(currentArg.join(''));
  }
  return result;
}

String? findOption(String option, List<String> args) {
  for (int i = 0; i < args.length - 1; ++i) {
    if (args[i] == option) {
      return args[i + 1];
    }
  }
  return null;
}

Iterable<String> findAllOptions(String option, List<String> args) sync* {
  for (int i = 0; i < args.length - 1; ++i) {
    if (args[i] == option) {
      yield args[i + 1];
    }
  }
}

// Print reports to stderr, to avoid polluting any stdout from the jobs.
void stderrPrintReport(
  int total,
  int completed,
  int inProgress,
  int pending,
  int failed,
) {
  stderr.write(ProcessPool.defaultReportToString(total, completed, inProgress, pending, failed));
}

Future<void> main(List<String> args) async {
  final ArgParser parser = ArgParser(usageLineLength: 80);
  parser.addFlag(
    _kHelpFlag,
    abbr: 'h',
    defaultsTo: false,
    negatable: false,
    help: 'Print help for $_kAppName.',
  );
  parser.addFlag(
    _kQuietFlag,
    abbr: 'q',
    defaultsTo: false,
    negatable: false,
    help: 'Silences the stderr and stdout output of the commands. This '
        'is a shorthand for "--no-$_kPrintStdoutFlag --no-$_kPrintStderrFlag".',
  );
  parser.addFlag(
    _kReportFlag,
    abbr: 'r',
    defaultsTo: false,
    negatable: false,
    help: 'Print progress on the jobs to stderr while running.',
  );
  parser.addFlag(
    _kPrintStdoutFlag,
    defaultsTo: true,
    help: 'Prints the stdout output of the commands to stdout in the order '
        'they complete. Will not interleave lines from separate processes. Has no '
        'effect if --$_kQuietFlag is specified.',
  );
  parser.addFlag(
    _kPrintStderrFlag,
    defaultsTo: true,
    help: 'Prints the stderr output of the commands to stderr in the order '
        'they complete. Will not interleave lines from separate processes. Has no '
        'effect if --$_kQuietFlag is specified',
  );
  parser.addFlag(
    _kRunInShellFlag,
    defaultsTo: false,
    negatable: false,
    help: 'Run the commands in a subshell.',
  );
  parser.addFlag(
    _kAllowFailureFlag,
    defaultsTo: false,
    help: 'If set, allows continuing execution of the remaining commands even if '
        'one fails to execute. If not set, ("--no-$_kAllowFailureFlag") then '
        'process will just exit with a non-zero code at completion if there were '
        'any jobs that failed.',
  );
  parser.addOption(
    _kJobsOption,
    abbr: 'j',
    help: 'Specify the number of worker jobs to run simultaneously. Defaults '
        'to the number of processor cores on the machine (which is '
        '${Platform.numberOfProcessors} on this machine).',
  );
  parser.addOption(
    _kWorkingDirectoryOption,
    defaultsTo: '.',
    help: 'Specify the working directory to run in.',
  );
  parser.addMultiOption(
    _kCommandOption,
    abbr: 'c',
    help: 'Specify a command to add to the commands to be run. Commands '
        'specified with this option run before those specified with '
        '--$_kSourceOption. Be sure to quote arguments to --$_kCommandOption '
        'properly on the command line.',
  );
  parser.addMultiOption(
    _kGroupOption,
    abbr: 'g',
    defaultsTo: <String>[],
    help: 'Specify the name of a file to read grouped commands from, one per '
        'line, as they would appear on the command line, with spaces escaped '
        'or quoted. More than one --$_kGroupOption argument may be specified, '
        'and each file will be run as a separate job group with the commands '
        'in each group run in the order specified in the file, but in parallel '
        'with other groups.',
  );
  parser.addMultiOption(
    _kSourceOption,
    abbr: 's',
    defaultsTo: <String>[],
    help: 'Specify the name of a file to read commands from, one per line, as '
        'they would appear on the command line, with spaces escaped or '
        'quoted. Specify "--$_kSourceOption -" to read from stdin. More than '
        'one --$_kSourceOption argument may be specified, and they will be '
        'run as separate tasks in parallel. The stdin '
        '("--$_kSourceOption -") argument may only be specified once.',
  );

  late ArgResults options;
  try {
    options = parser.parse(args);
  } on FormatException catch (e) {
    stderr.writeln('Argument Error: ${e.message}');
    stderr.writeln(parser.usage);
    exitCode = 1;
    return;
  }

  if (options[_kHelpFlag] as bool) {
    print(
      '$_kAppName [--${_kFlags.join('] [--')}] '
      '[--$_kWorkingDirectoryOption=<working directory>] '
      '[--$_kJobsOption=<num_worker_jobs>] '
      '[--$_kCommandOption="command" ...] '
      '[--$_kGroupOption=<file> ...] '
      '[--$_kSourceOption=<file|"-"> ...]:',
    );

    print(parser.usage);
    exitCode = 0;
    return;
  }

  final bool quiet = options[_kQuietFlag]! as bool;
  final bool printStderr = !quiet && options[_kPrintStderrFlag]! as bool;
  final bool printStdout = !quiet && options[_kPrintStdoutFlag]! as bool;
  final bool printReport = options[_kReportFlag]! as bool;
  final bool runInShell = options[_kRunInShellFlag]! as bool;
  final bool failOk = options[_kAllowFailureFlag]! as bool;

  // Collect the commands to be run from the command file(s).
  final List<String>? commandFiles = options[_kSourceOption] as List<String>?;
  // Collect all the commands, both from input files, and from the command
  // line. The command line commands are run first (although they could all
  // potentially be executed simultaneously, depending on the number of workers,
  // and number of commands).
  final List<List<String>> fileCommands = getCommandsFromFiles(commandFiles);

  final List<String> collectedCommands = <String>[
    if (options[_kCommandOption] != null) ...options[_kCommandOption]! as List<String>,
  ];
  fileCommands
      .forEach(collectedCommands.addAll); // Flatten the groups so they can be run in parallel.

  final List<List<String>> splitCommands =
      collectedCommands.map<List<String>>((String command) => splitIntoArgs(command)).toList();

  // Collect the commands to be run from the group file(s).
  final List<List<String>> groupCommands =
      getCommandsFromFiles(options[_kGroupOption] as List<String>, allowStdin: false);

  // Split each command entry into a list of strings, taking into account some
  // simple quoting and escaping.
  final List<List<List<String>>> splitGroupCommands = groupCommands
      .map<List<List<String>>>(
          (List<String> group) => group.map<List<String>>(splitIntoArgs).toList())
      .toList();

  // If the numWorkers is set to null, then the ProcessPool will automatically
  // select the number of processes based on how many CPU cores the machine has.
  final int? numWorkers = int.tryParse(options[_kJobsOption] as String? ?? '');
  final Directory workingDirectory =
      Directory((options[_kWorkingDirectoryOption] as String?) ?? '.');

  final ProcessPool pool = ProcessPool(
    numWorkers: numWorkers,
    printReport: printReport ? stderrPrintReport : null,
  );
  final Iterable<WorkerJobGroup> groupedJobs =
      splitGroupCommands.map<WorkerJobGroup>((List<List<String>> group) {
    return WorkerJobGroup(group
        .map<WorkerJob>((List<String> command) => WorkerJob(
              command,
              workingDirectory: workingDirectory,
              runInShell: runInShell,
              failOk: failOk,
            ))
        .toList());
  });
  final Iterable<WorkerJob> parallelJobs =
      splitCommands.map<WorkerJob>((List<String> command) => WorkerJob(
            command,
            workingDirectory: workingDirectory,
            runInShell: runInShell,
            failOk: failOk,
          ));
  final Iterable<DependentJob> jobs = parallelJobs.cast<DependentJob>().followedBy(groupedJobs);
  try {
    await for (final WorkerJob done in pool.startWorkers(jobs)) {
      if (printStdout) {
        stdout.write(done.result.stdout);
      }
      if (printStderr) {
        stderr.write(done.result.stderr);
      }
    }
  } on ProcessRunnerException catch (e) {
    if (!failOk) {
      stderr.writeln('$_kAppName execution failed: $e');
      exitCode = e.exitCode;
      return;
    }
  }

  // Return non-zero exit code if there were jobs that failed.
  exitCode = pool.failedJobs != 0 ? 1 : 0;
}

List<List<String>> getCommandsFromFiles(List<String>? commandFiles, {bool allowStdin = false}) {
  final List<List<String>> fileCommands = <List<String>>[];
  if (commandFiles != null) {
    bool sawStdinAlready = false;
    for (final String commandFile in commandFiles) {
      // Read from stdin if the --file option is set to '-'.
      if (allowStdin && commandFile == '-') {
        if (sawStdinAlready) {
          stderr.writeln('ERROR: The stdin can only be specified once with "--$_kSourceOption -"');
          exitCode = 1;
          return <List<String>>[];
        }
        sawStdinAlready = true;
        String? line = stdin.readLineSync();
        final List<String> commands = <String>[];
        while (line != null) {
          commands.add(line);
          line = stdin.readLineSync();
        }
        fileCommands.add(commands);
      } else {
        // Read the commands from a file.
        final File cmdFile = File(commandFile);
        if (!cmdFile.existsSync()) {
          print('''Command file "$commandFile" doesn't exist.''');
          exit(1);
        }
        fileCommands.add(cmdFile.readAsLinesSync());
      }
    }
  }
  return fileCommands;
}
