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

// Update the flakiness data with a set of fresh results.

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

import 'package:args/args.dart';

import 'package:test_runner/bot_results.dart';

void main(List<String> args) async {
  final parser = ArgParser();
  parser.addFlag('help', help: 'Show the program usage.', negatable: false);
  parser.addOption('input', abbr: 'i', help: 'Input flakiness file.');
  parser.addOption('output', abbr: 'o', help: 'Output flakiness file.');
  parser.addOption('build-id', help: 'Logdog ID of this buildbot run');
  parser.addOption('commit', help: 'Commit hash of this buildbot run');
  parser.addFlag('no-forgive', help: 'Don\'t remove any flaky records');

  final options = parser.parse(args);
  if (options['help']) {
    print('''
Usage: update_flakiness.dart [OPTION]... [RESULT-FILE]...
Update the flakiness data with a set of fresh results.

The options are as follows:

${parser.usage}''');
    return;
  }
  final parameters = options.rest;

  // Load the existing flakiness data, if any.
  final data = options['input'] != null
      ? await loadResultsMap(options['input'])
      : <String, Map<String, dynamic>>{};

  final resultsForInactiveFlakiness = {
    for (final flakyTest in data.keys)
      if (data[flakyTest]!['active'] == false) flakyTest: <String>{}
  };
  // Incrementally update the flakiness data with each observed result.
  for (final path in parameters) {
    final results = await loadResults(path);
    for (final resultObject in results) {
      final String configuration = resultObject['configuration'] /*!*/;
      final String name = resultObject['name'] /*!*/;
      final String result = resultObject['result'] /*!*/;
      final key = '$configuration:$name';
      resultsForInactiveFlakiness[key]?.add(result);
      Map<String, dynamic> newMap() => {};
      final testData = data.putIfAbsent(key, newMap);
      testData['configuration'] = configuration;
      testData['name'] = name;
      testData['expected'] = resultObject['expected'];
      final outcomes = testData.putIfAbsent('outcomes', () => []);
      final time = DateTime.now().toIso8601String();
      if (!outcomes.contains(result)) {
        outcomes
          ..add(result)
          ..sort();
        testData['last_new_result_seen'] = time;
      }
      if (testData['current'] == result) {
        testData['current_counter']++;
      } else {
        testData['current'] = result;
        testData['current_counter'] = 1;
      }
      final occurrences = testData.putIfAbsent('occurrences', newMap);
      occurrences.putIfAbsent(result, () => 0);
      occurrences[result]++;
      final firstSeen = testData.putIfAbsent('first_seen', newMap);
      firstSeen.putIfAbsent(result, () => time);
      final lastSeen = testData.putIfAbsent('last_seen', newMap);
      lastSeen[result] = time;
      final matches = testData.putIfAbsent('matches', newMap);
      matches[result] = resultObject['matches'];

      if (options['build-id'] != null) {
        final buildIds = testData.putIfAbsent('build_ids', newMap);
        buildIds[result] = options['build-id'];
      }
      if (options['commit'] != null) {
        final commits = testData.putIfAbsent('commits', newMap);
        commits[result] = options['commit'];
      }
    }
  }

  // Write out the new flakiness data.
  final sink =
      options['output'] != null ? File(options['output']).openWrite() : stdout;
  final keys = data.keys.toList()..sort();
  for (final key in keys) {
    final testData = data[key]!;
    if (testData['outcomes'].length < 2) continue;
    // Reactivate inactive flaky results that are flaky again.
    if (testData['active'] == false) {
      if (resultsForInactiveFlakiness[key]!.length > 1) {
        testData['active'] = true;
        testData['reactivation_count'] =
            (testData['reactivation_count'] ?? 0) + 1;
      }
    } else if (!options['no-forgive'] && testData['current_counter'] >= 100) {
      // Forgive tests that have been stable for 100 builds.
      testData['active'] = false;
    } else {
      testData['active'] = true;
    }

    sink.writeln(jsonEncode(testData));
  }
}
