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

/// [Configuration] holds information about a specific configuration, parsed
/// from a JSON result.log file.
/// TODO(mkroghj): Needs a shared package to keep information in sync with
/// test.py.
class Configuration {
  final String mode;
  final String arch;
  final String compiler;
  final String runtime;
  final bool checked;
  final bool strong;
  final bool hostChecked;
  final bool minified;
  final bool csp;
  final bool fasta;
  final String system;
  final List<String> vmOptions;
  final bool useSdk;
  final String builderTag;
  final bool fastStartup;
  final int timeout;
  final bool enableAsserts;
  final bool hotReload;
  final bool hotReloadRollback;
  final bool noPreviewDart2;
  final List<String> selectors;

  Configuration(
      this.mode,
      this.arch,
      this.compiler,
      this.runtime,
      this.checked,
      this.strong,
      this.hostChecked,
      this.minified,
      this.csp,
      this.fasta,
      this.system,
      this.vmOptions,
      this.useSdk,
      this.builderTag,
      this.fastStartup,
      this.timeout,
      this.enableAsserts,
      this.hotReload,
      this.hotReloadRollback,
      this.noPreviewDart2,
      this.selectors);

  static Configuration getFromJson(dynamic json) {
    var isStrong = !(json["no_preview_dart_2"] ?? false);
    return new Configuration(
        json["mode"],
        json["arch"],
        json["compiler"],
        json["runtime"],
        json["checked"],
        isStrong,
        json["host_checked"],
        json["minified"],
        json["csp"],
        json["fasta"],
        json["system"],
        json["vm_options"].cast<String>(),
        json["use_sdk"],
        json["builder_tag"],
        json["fast_startup"],
        json["timeout"],
        json["enable_asserts"] ?? false,
        json["hot_reload"] ?? false,
        json["hot_reload_rollback"] ?? false,
        !isStrong,
        json["selectors"].cast<String>() ?? <String>[]);
  }

  /// Returns the arguments needed for running test.py with the arguments
  /// corresponding to this configuration.
  List<String> toArgs({includeSelectors: true}) {
    var args = [
      _stringToArg("mode", mode),
      _stringToArg("arch", arch),
      _stringToArg("compiler", compiler),
      _stringToArg("runtime", runtime),
      _boolToArg("checked", checked),
      _boolToArg("strong", strong),
      _boolToArg("host-checked", hostChecked),
      _boolToArg("minified", minified),
      _boolToArg("csp", csp),
      // We don't create a --fasta arg because fasta is synthesized variable.
      _stringToArg("system", system),
      _listToArg("vm-options", vmOptions),
      _boolToArg("use-sdk", useSdk),
      _stringToArg("builder-tag", builderTag),
      _boolToArg("fast-startup", fastStartup),
      _boolToArg("enable-asserts", enableAsserts),
      _boolToArg("hot-reload", hotReload),
      _boolToArg("hot-reload-rollback", hotReloadRollback),
      _boolToArg("no-preview-dart-2", noPreviewDart2)
    ].where((x) => x != null).toList();
    if (includeSelectors && selectors != null && selectors.length > 0) {
      args.addAll(selectors);
    }
    return args;
  }

  String toCsvString() {
    return "$mode;$arch;$compiler;$runtime;$checked;$strong;$hostChecked;"
        "$minified;$csp;$fasta;$system;$vmOptions;$useSdk;$builderTag;$fastStartup;"
        "$enableAsserts;$hotReload;"
        "$hotReloadRollback;$noPreviewDart2;$selectors";
  }

  String _stringToArg(String name, String value) {
    if (value == null || value.length == 0) {
      return null;
    }
    return "--$name=$value";
  }

  String _boolToArg(String name, bool value) {
    return value == true ? "--$name" : null;
  }

  String _listToArg(String name, List<String> strings) {
    if (strings == null || strings.length == 0) {
      return null;
    }
    return "--$name=${strings.join(',')}";
  }
}

/// [Result] contains the [result] of executing a single test on a specified
/// [configuration].
class Result {
  // Not final since we have to update it when combining test results.
  String configuration;
  final String name;
  final String result;
  final bool flaky;
  final bool negative;
  final List<String> testExpectations;
  final List<Command> commands;

  Result(this.configuration, this.name, this.result, this.flaky, this.negative,
      this.testExpectations, this.commands);

  static Result getFromJson(dynamic json) {
    var commands =
        json["commands"].map<Command>((x) => Command.getFromJson(x)).toList();
    var testExpectations = json["test_expectation"].cast<String>();
    return new Result(json["configuration"], json["name"], json["result"],
        json["flaky"], json["negative"], testExpectations, commands);
  }
}

/// [Command] used to get a result for a test.
class Command {
  final String name;
  final int exitCode;
  final bool timeout;
  final int duration;

  Command(this.name, this.exitCode, this.timeout, this.duration);

  static Command getFromJson(dynamic json) {
    return new Command(
        json["name"], json["exitCode"], json["timeout"], json["duration"]);
  }
}

/// [TestResult] is a collection of configurations and test results,
/// corresponding to the information found in a result.log json file.
class TestResult {
  final dynamic jsonObject;

  TestResult() : jsonObject = null {
    _configurations = {};
    _results = [];
  }

  TestResult.fromJson(this.jsonObject);

  Map<String, Configuration> _configurations;
  Map<String, Configuration> get configurations {
    if (_configurations != null) {
      return _configurations;
    }
    _configurations = {};
    this.jsonObject["configurations"].forEach((key, value) {
      _configurations[key] = Configuration.getFromJson(value);
    });
    return _configurations;
  }

  List<Result> _results;
  List<Result> get results {
    return _results ??= this
        .jsonObject["results"]
        .map<Result>((x) => Result.getFromJson(x))
        .toList();
  }

  /// Combines multiple test-results into a single test-result, potentially by
  /// giving new names to later configurations.
  void combineWith(Iterable<TestResult> results) {
    results.forEach((tr) {
      Map<String, String> translatedConfigurations = {};
      for (var confKey in tr.configurations.keys) {
        var newKey = _findExistingConfiguration(
            tr.configurations[confKey], this.configurations);
        newKey ??= "conf${this.configurations.length + 1}";
        translatedConfigurations[confKey] = newKey;
        this.configurations[newKey] = tr.configurations[confKey];
      }
      this.results.addAll(tr.results.map((res) {
        res.configuration = translatedConfigurations[res.configuration];
        return res;
      }));
    });
  }

  /// Finds an existing configuration based on the arguments passed to test.py.
  String _findExistingConfiguration(Configuration configurationToFind,
      Map<String, Configuration> existingConfigurations) {
    String thisArgs = configurationToFind.toArgs().join();
    for (var confKey in existingConfigurations.keys) {
      String confArgs = existingConfigurations[confKey].toArgs().join();
      if (confArgs == thisArgs) {
        return confKey;
      }
    }
    return null;
  }
}
