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

// results.json and flaky.json parses.

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

/// gsutil.py binary to use.
final gsutil = Platform.isWindows ? "gsutil.py.bat" : "gsutil.py";

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

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

/// 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 {
  final processResult = await Process.run(gsutil, arguments,
      environment: {"DEPOT_TOOLS_UPDATE": "0"});
  if (processResult.exitCode != 0) {
    if (processResult.exitCode == 1 &&
            processResult.stderr.contains("No URLs matched") ||
        processResult.stderr.contains("One or more URLs matched no objects")) {
      return null;
    }
    throw new Exception("Failed to run: $gsutil $arguments\n"
        "exitCode: ${processResult.exitCode}\n"
        "stdout:\n${processResult.stdout}\n"
        "stderr:\n${processResult.stderr}");
  }
  return processResult.stdout;
}

/// 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 {
  final contents = await runGsutil(["ls", directory]);
  if (contents == null) {
    return null;
  }
  return LineSplitter.split(contents).map((String path) {
    final 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 {
  final results = <Map<String, dynamic>>[];
  final lines = new File(path)
      .openRead()
      .transform(utf8.decoder)
      .transform(new LineSplitter());
  await for (final line in lines) {
    final Map<String, dynamic> map = jsonDecode(line);
    results.add(map);
  }
  return results;
}

Map<String, Map<String, dynamic>> createResultsMap(
        List<Map<String, dynamic>> results) =>
    new Map<String, Map<String, dynamic>>.fromIterable(results,
        key: (dynamic result) =>
            "${result["configuration"]}:${result["name"]}");

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));
