#!/usr/bin/env dart
// 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.

// Find the newest commit that has a full set of results on the builders.

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

import 'package:args/args.dart';
import 'package:glob/glob.dart';

void main(List<String> args) async {
  final parser = ArgParser();
  parser.addMultiOption("builder",
      abbr: "b",
      help: "Select the builders matching the glob [option is repeatable]",
      splitCommas: false);
  parser.addOption("branch",
      abbr: "B",
      help: "Select the builders building this branch",
      defaultsTo: "main");
  parser.addOption("count",
      abbr: "c", help: "List this many commits", defaultsTo: "1");
  parser.addFlag("help", help: "Show the program usage.", negatable: false);

  final options = parser.parse(args);
  if (options.flag("help")) {
    print("""
Usage: find_base_commit.dart [OPTION]...
Find the newest commit that has a full set of results on the builders.

The options are as follows:

${parser.usage}""");
    return;
  }

  int count = int.parse(options.option("count")!);
  final globs = List<Glob>.from(
      options.multiOption("builder").map((String pattern) => Glob(pattern)));

  // Download the most recent builds from buildbucket.
  const maxBuilds = 1000;
  final url = Uri.parse("https://cr-buildbucket.appspot.com"
      "/prpc/buildbucket.v2.Builds/SearchBuilds");
  const maxRetries = 3;
  const timeout = Duration(seconds: 30);
  final query = jsonEncode({
    "predicate": {
      "builder": {"project": "dart", "bucket": "ci.sandbox"},
      "status": "ENDED_MASK"
    },
    "pageSize": maxBuilds,
    "fields": "builds.*.builder.builder,builds.*.input"
  });
  late Map<String, dynamic> searchResult;
  for (int i = 1; i <= maxRetries; i++) {
    try {
      final client = HttpClient();
      final request = await client.postUrl(url).timeout(timeout)
        ..headers.contentType = ContentType.json
        ..headers.add(HttpHeaders.acceptHeader, ContentType.json)
        ..write(query);
      final response = await request.close().timeout(timeout);
      if (response.statusCode != 200) {
        print("Failed to search for builds: "
            "${response.statusCode}:${response.reasonPhrase}");
        exit(1);
      }
      const prefix = ")]}'";
      searchResult = await (response
          .cast<List<int>>()
          .transform(Utf8Decoder())
          .map((event) =>
              event.startsWith(prefix) ? event.substring(prefix.length) : event)
          .transform(JsonDecoder())
          .cast<Map<String, dynamic>>()
          .first
          .timeout(timeout));
      client.close();
      break;
    } on TimeoutException catch (e) {
      final inSeconds = e.duration?.inSeconds;
      stderr.writeln(
          "Attempt $i of $maxRetries timed out after $inSeconds seconds");
      if (i == maxRetries) {
        stderr.writeln("error: Failed to download $url");
        exit(1);
      }
    }
  }

  // Locate the builds we're interested in and map them to each commit. The
  // builds returned by the API are sorted with the newest first. Since builders
  // don't build back in time and always build the latest commit whenever they
  // can, the first time we see a commit, we know it's newer than all commits
  // we haven't seen yet. The insertion order into the buildersForCommits map
  // will then sorted with the newest commit first.
  final builds = searchResult["builds"] as List?;
  if (builds == null) {
    print("No builds found");
    exit(1);
  }
  final buildersForCommits = <String, Set<String>>{};
  for (final build in builds) {
    final builder = (build["builder"] as Map?)?["builder"];
    if (builder is! String ||
        builder.endsWith("-beta") ||
        builder.endsWith("-dev") ||
        builder.endsWith("-stable")) {
      // Ignore the release builders. The -try builders aren't in the
      // bucket we're reading.
      continue;
    }
    if (globs.isNotEmpty && !globs.any((glob) => glob.matches(builder))) {
      // Filter way builders we're not interested in.
      continue;
    }
    final input = (build["input"] as Map?)?["gitilesCommit"] as Map?;
    if (input == null) {
      // Ignore builds not triggered by a commit, e.g. fuzz-linux.
      continue;
    }
    final ref = input["ref"];
    if (ref != "refs/heads/${options.option('branch')}") {
      // Ignore builds on the wrong branch.
      continue;
    }
    final commit = input["id"] as String;
    final buildersForCommit =
        buildersForCommits.putIfAbsent(commit, () => <String>{});
    buildersForCommit.add(builder);
  }

  if (buildersForCommits.isEmpty) {
    print("Failed to locate any commits having run on the builders");
    exitCode = 1;
    return;
  }

  int maxBots = 0;
  for (final builders in buildersForCommits.values) {
    maxBots = max(maxBots, builders.length);
  }

  // List commits run on the most builders.
  for (final commit in buildersForCommits.keys
      .where((commit) => buildersForCommits[commit]!.length == maxBots)
      .take(count)) {
    print(commit);
  }
}
