// 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.

/// Parses results.json and flaky.json.

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math' as math;

import 'package:pool/pool.dart';

/// The path to the gsutil script.
late String gsutilPy;

// TODO(karlklose):  Update this class with all fields that
// are used in pkg/test_runner and the tools/bots scripts and include
// validation (in particular for fields from extend_results.dart, that are
// optional but expected in some contexts and should always be all or nothing).
class Result {
  final String configuration;
  final String expectation;
  final bool matches;
  final String name;
  final String outcome;
  final bool? changed;
  final String? commitHash;
  final bool flaked; // From optional flakiness_data argument to constructor.
  final bool? isFlaky; // From results.json after it is extended.
  final String? previousOutcome;

  Result(
    this.configuration,
    this.name,
    this.outcome,
    this.expectation,
    this.matches,
    this.changed,
    this.commitHash,
    this.isFlaky,
    this.previousOutcome, {
    this.flaked = false,
  });

  Result.fromMap(
    Map<String, dynamic> map, [
    Map<String, dynamic>? flakinessData,
  ])  : configuration = map["configuration"] as String,
        name = map["name"] as String,
        outcome = map["result"] as String,
        expectation = map["expected"] as String,
        matches = map["matches"] as bool,
        changed = map["changed"] as bool?,
        commitHash = map["commit_hash"] as String?,
        isFlaky = map["flaky"] as bool?,
        previousOutcome = map["previous_result"] as String?,
        flaked = flakinessData != null &&
            (flakinessData["active"] ?? true) == true &&
            (flakinessData["outcomes"] as List).contains(map["result"]);

  String get key => "$configuration:$name";
}

/// Cloud storage location containing results.
const testResultsStoragePath = "gs://dart-test-results/builders";

/// Limit the number of concurrent subprocesses by half the number of cores.
final gsutilPool = Pool(math.max(1, Platform.numberOfProcessors ~/ 2));

/// Runs gsutil with the provided [arguments] and returns the standard output.
///
/// Returns null if the requested URL didn't exist.
Future<String> runGsutil(List<String> arguments) async {
  return gsutilPool.withResource(() async {
    var processResult = await Process.run(
        "python3", [gsutilPy]..addAll(arguments),
        runInShell: Platform.isWindows);
    if (processResult.exitCode != 0) {
      var stderr = processResult.stderr as String;
      if (processResult.exitCode == 1 && stderr.contains("No URLs matched") ||
          stderr.contains("One or more URLs matched no objects")) {
        return "";
      }
      var error = "Failed to run: python3 $gsutilPy $arguments\n"
          "exitCode: ${processResult.exitCode}\n"
          "stdout:\n${processResult.stdout}\n"
          "stderr:\n${processResult.stderr}";
      if (processResult.exitCode == 1 &&
          stderr.contains("401 Anonymous caller")) {
        error =
            "\n\nYou need to authenticate by running:\npython3 $gsutilPy config\n";
      }
      throw Exception(error);
    }
    return processResult.stdout as String;
  });
}

/// Returns the contents of the provided cloud storage [path], or null if it
/// didn't exist.
Future<String> catGsutil(String path) => runGsutil(["cat", path]);

/// Returns the files and directories in the provided cloud storage [directory],
/// or null if it didn't exist.
Future<Iterable<String>> lsGsutil(String directory) async {
  var contents = await runGsutil(["ls", directory]);
  if (contents.isEmpty) {
    return const [];
  }
  return LineSplitter.split(contents).map((String path) {
    var elements = path.split("/");
    if (elements[elements.length - 1].isEmpty) {
      return elements[elements.length - 2];
    } else {
      return elements[elements.length - 1];
    }
  });
}

/// Copies a file to or from cloud storage.
Future cpGsutil(String source, String destination) =>
    runGsutil(["cp", source, destination]);

/// Copies a directory recursively to or from cloud strorage.
Future cpRecursiveGsutil(String source, String destination) =>
    runGsutil(["-m", "cp", "-r", "-Z", source, destination]);

/// Lists the bots in cloud storage.
Future<Iterable<String>> listBots() => lsGsutil("$testResultsStoragePath");

/// Returns the cloud storage path for the [bot].
String botCloudPath(String bot) => "$testResultsStoragePath/$bot";

/// Returns the cloud storage path to the [build] on the [bot].
String buildCloudPath(String bot, String build) =>
    "${botCloudPath(bot)}/$build";

/// Returns the cloud storage path to the [file] inside the [bot]'s directory.
String fileCloudPath(String bot, String file) => "${botCloudPath(bot)}/$file";

/// Reads the contents of the [file] inside the [bot]'s cloud storage.
Future<String> readFile(String bot, String file) =>
    catGsutil(fileCloudPath(bot, file));

/// Returns the cloud storage path to the [file] inside the [build] on the
/// [bot].
String buildFileCloudPath(String bot, String build, String file) =>
    "${buildCloudPath(bot, build)}/$file";

/// Reads the contents of the [file] inside the [build] in the [bot]'s cloud
/// storage.
Future<String> readBuildFile(String bot, String build, String file) =>
    catGsutil(buildFileCloudPath(bot, build, file));

List<Map<String, dynamic>> parseResults(String contents) {
  return LineSplitter.split(contents)
      .map(jsonDecode)
      .toList()
      .cast<Map<String, dynamic>>();
}

Future<List<Map<String, dynamic>>> loadResults(String path) async {
  var results = <Map<String, dynamic>>[];
  var lines = File(path)
      .openRead()
      .cast<List<int>>()
      .transform(utf8.decoder)
      .transform(const LineSplitter());
  await for (var line in lines) {
    results.add(jsonDecode(line) as Map<String, dynamic>);
  }
  return results;
}

Map<String, Map<String, dynamic>> createResultsMap(
    List<Map<String, dynamic>> results) {
  var result = <String, Map<String, dynamic>>{};
  for (var map in results) {
    var key = "${map["configuration"]}:${map["name"]}";
    result.putIfAbsent(key, () => map);
  }
  return result;
}

Map<String, Map<String, dynamic>> parseResultsMap(String contents) =>
    createResultsMap(parseResults(contents));

Future<Map<String, Map<String, dynamic>>> loadResultsMap(String path) async =>
    createResultsMap(await loadResults(path));
