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

library dartdoc.tool_runner;

import 'dart:async';
import 'dart:io';

import 'package:dartdoc/src/io_utils.dart';
import 'package:path/path.dart' as path;
import 'dartdoc_options.dart';

typedef ToolErrorCallback = void Function(String message);
typedef FakeResultCallback = String Function(String tool,
    {List<String> args, String content});

/// Set a ceiling on how many tool instances can be in progress at once,
/// limiting both parallelization and the number of open temporary files.
final MultiFutureTracker _toolTracker = new MultiFutureTracker(4);

/// Can be called when the ToolRunner is no longer needed.
///
/// This will remove any temporary files created by the tool runner.
class ToolTempFileTracker {
  final Directory temporaryDirectory;

  ToolTempFileTracker._()
      : temporaryDirectory =
            Directory.systemTemp.createTempSync('dartdoc_tools_');

  static ToolTempFileTracker _instance;

  static ToolTempFileTracker get instance =>
      _instance ??= ToolTempFileTracker._();

  int _temporaryFileCount = 0;

  Future<File> createTemporaryFile() async {
    _temporaryFileCount++;
    File tempFile = new File(path.join(
        temporaryDirectory.absolute.path, 'input_$_temporaryFileCount'));
    await tempFile.create(recursive: true);
    return tempFile;
  }

  /// Call once no more files are to be created.
  Future<void> dispose() async {
    if (temporaryDirectory.existsSync()) {
      return temporaryDirectory.delete(recursive: true);
    }
  }
}

/// A helper class for running external tools.
class ToolRunner {
  /// Creates a new ToolRunner.
  ///
  /// Takes a [toolConfiguration] that describes all of the available tools.
  /// An optional `errorCallback` will be called for each error message
  /// generated by the tool.
  ToolRunner(this.toolConfiguration);

  final ToolConfiguration toolConfiguration;

  void _runSetup(
      String name,
      ToolDefinition tool,
      Map<String, String> environment,
      ToolErrorCallback toolErrorCallback) async {
    bool isDartSetup = ToolDefinition.isDartExecutable(tool.setupCommand[0]);
    var args = tool.setupCommand.toList();
    String commandPath;

    if (isDartSetup) {
      commandPath = Platform.resolvedExecutable;
    } else {
      commandPath = args.removeAt(0);
    }
    await _runProcess(
        name, '', commandPath, args, environment, toolErrorCallback);
    tool.setupComplete = true;
  }

  Future<String> _runProcess(
      String name,
      String content,
      String commandPath,
      List<String> args,
      Map<String, String> environment,
      ToolErrorCallback toolErrorCallback) async {
    String commandString() => ([commandPath] + args).join(' ');
    try {
      ProcessResult result =
          await Process.run(commandPath, args, environment: environment);
      if (result.exitCode != 0) {
        toolErrorCallback('Tool "$name" returned non-zero exit code '
            '(${result.exitCode}) when run as '
            '"${commandString()}" from ${Directory.current}\n'
            'Input to $name was:\n'
            '$content\n'
            'Stderr output was:\n${result.stderr}\n');
        return '';
      } else {
        return result.stdout;
      }
    } on ProcessException catch (exception) {
      toolErrorCallback('Failed to run tool "$name" as '
          '"${commandString()}": $exception\n'
          'Input to $name was:\n'
          '$content');
      return '';
    }
  }

  /// Run a tool.  The name of the tool is the first argument in the [args].
  /// The content to be sent to to the tool is given in the optional [content],
  /// and the stdout of the tool is returned.
  ///
  /// The [args] must not be null, and it must have at least one member (the name
  /// of the tool).
  Future<String> run(List<String> args, ToolErrorCallback toolErrorCallback,
      {String content, Map<String, String> environment}) async {
    Future runner;
    // Prevent too many tools from running simultaneously.
    await _toolTracker.addFutureFromClosure(() {
      runner = _run(args, toolErrorCallback,
          content: content, environment: environment);
      return runner;
    });
    return runner;
  }

  Future<String> _run(List<String> args, ToolErrorCallback toolErrorCallback,
      {String content, Map<String, String> environment}) async {
    assert(args != null);
    assert(args.isNotEmpty);
    content ??= '';
    environment ??= <String, String>{};
    var tool = args.removeAt(0);
    if (!toolConfiguration.tools.containsKey(tool)) {
      toolErrorCallback(
          'Unable to find definition for tool "$tool" in tool map. '
          'Did you add it to dartdoc_options.yaml?');
      return '';
    }
    ToolDefinition toolDefinition = toolConfiguration.tools[tool];
    var toolArgs = toolDefinition.command;
    // Ideally, we would just be able to send the input text into stdin, but
    // there's no way to do that synchronously, and converting dartdoc to an
    // async model of execution is a huge amount of work. Using dart:cli's
    // waitFor feels like a hack (and requires a similar amount of work anyhow
    // to fix order of execution issues). So, instead, we have the tool take a
    // filename as part of its arguments, and write the input to a temporary
    // file before running the tool synchronously.

    // Write the content to a temp file.
    var tmpFile = await ToolTempFileTracker.instance.createTemporaryFile();
    await tmpFile.writeAsString(content);

    // Substitute the temp filename for the "$INPUT" token, and all of the other
    // environment variables. Variables are allowed to either be in $(VAR) form,
    // or $VAR form.
    var envWithInput = {
      'INPUT': tmpFile.absolute.path,
      'TOOL_COMMAND': toolDefinition.command[0]
    }..addAll(environment);
    if (toolDefinition is DartToolDefinition) {
      // Put the original command path into the environment, because when it
      // runs as a snapshot, Platform.script (inside the tool script) refers to
      // the snapshot, and not the original script.  This way at least, the
      // script writer can use this instead of Platform.script if they want to
      // find out where their script was coming from as an absolute path on the
      // filesystem.
      envWithInput['DART_SNAPSHOT_CACHE'] =
          SnapshotCache.instance.snapshotCache.absolute.path;
      if (toolDefinition.setupCommand != null) {
        envWithInput['DART_SETUP_COMMAND'] = toolDefinition.setupCommand[0];
      }
    }
    var substitutions = envWithInput.map<RegExp, String>((key, value) {
      String escapedKey = RegExp.escape(key);
      return MapEntry(RegExp('\\\$(\\($escapedKey\\)|$escapedKey\\b)'), value);
    });
    var argsWithInput = <String>[];
    for (var arg in args) {
      var newArg = arg;
      substitutions
          .forEach((regex, value) => newArg = newArg.replaceAll(regex, value));
      argsWithInput.add(newArg);
    }

    if (toolDefinition.setupCommand != null && !toolDefinition.setupComplete) {
      await _runSetup(tool, toolDefinition, envWithInput, toolErrorCallback);
    }

    argsWithInput = toolArgs + argsWithInput;
    var commandPath;
    void Function() callCompleter;
    if (toolDefinition is DartToolDefinition) {
      var modified = await toolDefinition
          .modifyArgsToCreateSnapshotIfNeeded(argsWithInput);
      commandPath = modified.item1;
      callCompleter = modified.item2;
    } else {
      commandPath = argsWithInput.removeAt(0);
    }

    if (callCompleter != null) {
      return _runProcess(tool, content, commandPath, argsWithInput,
              envWithInput, toolErrorCallback)
          .whenComplete(callCompleter);
    } else {
      return _runProcess(tool, content, commandPath, argsWithInput,
          envWithInput, toolErrorCallback);
    }
  }
}
