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

import 'configuration.dart';

/// A step that is run on a builder to build and test certain configurations of
/// the Dart SDK.
///
/// Each step on a builder runs a script the with provided arguments. If the
/// script is 'tools/test.py' (which is the default if no script is given in
/// the test matrix), or `testRunner == true`, the step is called a 'test
/// step'. Test steps must include the '--named_configuration' (for short
/// '-n') option to select the named [Configuration] to test.
///
/// Test steps are expected to produce test results that are collected during
/// the run of the builder and checked against the expected results to determine
/// the success or failure of the build.
class Step {
  final String name;
  final String script;
  final List<String> arguments;
  final Map<String, String> environment;
  final String? fileSet;
  final int? shards;
  final bool isTestRunner;
  final Configuration? testedConfiguration;

  Step(this.name, String? script, this.arguments, this.environment,
      this.fileSet, this.shards, this.isTestRunner, this.testedConfiguration)
      : script = script ?? testScriptName;

  static const testScriptName = "tools/test.py";

  bool get isTestStep => script == testScriptName || isTestRunner;

  /// Create a [Step] from the 'step template' [map], values for supported
  /// variables [configuration], and the list of supported named configurations.
  static Step parse(Map map, Map<String, String?> configuration,
      List<Configuration> configurations) {
    var arguments = (map["arguments"] as List? ?? [])
        .map((argument) => _expandVariables(argument as String, configuration))
        .toList();
    var testedConfigurations = <Configuration>[];
    var script = map["script"] as String? ?? testScriptName;
    var isTestRunner = map["testRunner"] as bool? ?? false;
    if (script == testScriptName || isTestRunner) {
      // TODO(karlklose): replace with argument parser that can handle all
      // arguments to test.py.
      for (var argument in arguments) {
        var names = <String>[];
        if (argument.startsWith("--named_configuration")) {
          names.addAll(argument
              .substring("--named_configuration".length)
              .split(",")
              .map((s) => s.trim()));
        } else if (argument.startsWith("-n")) {
          names.addAll(
              argument.substring("-n".length).split(",").map((s) => s.trim()));
        } else {
          continue;
        }
        for (var name in names) {
          var matchingConfigurations =
              configurations.where((c) => c.name == name);
          if (matchingConfigurations.isEmpty) {
            throw FormatException("Undefined configuration: $name");
          }
          testedConfigurations.add(matchingConfigurations.single);
        }
      }
      if (testedConfigurations.length > 1) {
        throw FormatException("Step tests multiple configurations: $arguments");
      }
    }
    var environment = map["environment"] as Map<Object?, Object?>?;
    return Step(
        map["name"] as String,
        script,
        arguments,
        {...?environment?.cast<String, String>()},
        map["fileset"] as String?,
        map["shards"] as int?,
        isTestRunner,
        testedConfigurations.isEmpty ? null : testedConfigurations.single);
  }
}

/// A builder runs a list of [Step]s to build and test certain configurations of
/// the Dart SDK.
///
/// Groups of builders are defined in the 'builder_configurations' section of
/// the test matrix.
class Builder {
  final String name;
  final String? description;
  final List<Step> steps;
  final System? system;
  final Mode? mode;
  final Architecture? arch;
  final Sanitizer? sanitizer;
  final Runtime? runtime;
  final Set<Configuration> testedConfigurations;

  Builder(this.name, this.description, this.steps, this.system, this.mode,
      this.arch, this.sanitizer, this.runtime, this.testedConfigurations);

  /// Create a [Builder] from its name, a list of 'step templates', the
  /// supported named configurations and a description.
  ///
  /// The 'step templates' can contain the variables `${system}`, `${mode}`,
  /// `${arch}`, and `${runtime}. The values for these variables are inferred
  /// from the builder's name.
  static Builder parse(String builderName, List<Map> steps,
      List<Configuration> configurations, String? description) {
    var builderParts = builderName.split("-");
    var systemName = _findPart(builderParts, System.names, 'linux');
    var modeName = _findPart(builderParts, Mode.names, 'release');
    var archName = _findPart(builderParts, Architecture.names, 'x64');
    var sanitizerName = _findPart(builderParts, Sanitizer.names);
    var runtimeName = _findPart(builderParts, Runtime.names);
    var parsedSteps = steps
        .map((step) => Step.parse(
            step,
            {
              "system": systemName,
              "mode": modeName,
              "arch": archName,
              "sanitizer": sanitizerName,
              "runtime": runtimeName,
            },
            configurations))
        .toList();
    var testedConfigurations = _getTestedConfigurations(parsedSteps);
    return Builder(
        builderName,
        description,
        parsedSteps,
        _findIfNotNull(System.find, systemName),
        _findIfNotNull(Mode.find, modeName),
        _findIfNotNull(Architecture.find, archName),
        _findIfNotNull(Sanitizer.find, sanitizerName),
        _findIfNotNull(Runtime.find, runtimeName),
        testedConfigurations);
  }
}

/// Tries to replace a variable named [variableName] with [value] and throws
/// and exception if the variable is used but `value == null`.
String _tryReplace(String string, String variableName, String? value) {
  var variable = "\${$variableName}";
  if (string.contains(variable)) {
    if (value == null) {
      throw FormatException("Undefined value for '$variableName' in '$string'");
    }
    return string.replaceAll(variable, value);
  } else {
    return string;
  }
}

/// Replace the use of supported variable names with the their value given
/// in [values] and throws an exception if an unsupported variable name is used.
String _expandVariables(String string, Map<String, String?> values) {
  for (var variable in ["system", "mode", "arch", "sanitizer", "runtime"]) {
    string = _tryReplace(string, variable, values[variable]);
  }
  return string;
}

Set<Configuration> _getTestedConfigurations(List<Step> steps) {
  return steps
      .where((step) => step.isTestStep)
      .map((step) => step.testedConfiguration)
      .whereType<Configuration>()
      .toSet();
}

T? _findIfNotNull<T>(T Function(String) find, String? name) {
  return name != null ? find(name) : null;
}

String? _findPart(List<String> builderParts, List<String> parts,
    [String? fallback]) {
  return builderParts
      .cast<String?>()
      .firstWhere((part) => parts.contains(part), orElse: () => fallback);
}

List<Builder> parseBuilders(
    List<Map> builderConfigurations, List<Configuration> configurations) {
  var builders = <Builder>[];
  var names = <String>{};
  for (var builderConfiguration in builderConfigurations) {
    var meta = builderConfiguration["meta"] as Map? ?? <String, String>{};
    var builderNames = builderConfiguration["builders"] as List<Object?>?;
    if (builderNames != null) {
      var steps = ((builderConfiguration["steps"] ?? []) as List<Object?>)
          .cast<Map<Object?, Object?>>();
      for (var builderName in builderNames.cast<String>()) {
        if (!names.add(builderName)) {
          throw FormatException('Duplicate builder name: "$builderName"');
        }
        builders.add(Builder.parse(builderName, steps, configurations,
            meta["description"] as String?));
      }
    }
  }
  return builders;
}
