// Copyright (c) 2022, 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.md file.

library fasta.test.suite_utils;

import 'package:testing/testing.dart' show Step, TestDescription;
import 'package:testing/src/chain.dart' show CreateContext;
import 'package:testing/src/log.dart' show Logger, StdoutLogger;
import 'package:testing/src/suite.dart' as testing show Suite;

import 'testing/suite.dart';

Future<void> internalMain(CreateContext createContext,
    {List<String> arguments = const [], int shards = 1, int shard = 0}) async {
  Logger logger = const StdoutLogger();
  if (arguments.contains("--traceStepTiming")) {
    logger = new TracingLogger();
    arguments = arguments.toList()..remove("--traceStepTiming");
  }
  await runMe(
    arguments,
    createContext,
    configurationPath: "../../testing.json",
    shards: shards,
    shard: shard,
    logger: logger,
  );
}

class TracingLogger extends StdoutLogger {
  Map<TestDescription, Map<Step, Stopwatch>> stopwatches = {};

  @override
  void logStepStart(int completed, int failed, int total, testing.Suite? suite,
      TestDescription description, Step step) {
    Map<Step, Stopwatch> map = stopwatches[description] ??= {};
    Stopwatch stopwatch = map[step] ??= new Stopwatch();
    if (stopwatch.isRunning) throw "unexpectedly already running @ $step";
    stopwatch.start();
    super.logStepStart(completed, failed, total, suite, description, step);
  }

  @override
  void logStepComplete(int completed, int failed, int total,
      testing.Suite? suite, TestDescription description, Step step) {
    Map<Step, Stopwatch> map = stopwatches[description]!;
    Stopwatch stopwatch = map[step] = map[step]!;
    if (!stopwatch.isRunning) throw "unexpectedly not running";
    stopwatch.stop();
    super.logStepComplete(completed, failed, total, suite, description, step);
  }

  @override
  void logSuiteComplete(testing.Suite suite) {
    Map<String, Duration> totalRuntimesForSteps = {};
    // Make sure not to overwrite existing text about number of tests run,
    // failures etc.
    print("");
    print("");

    for (MapEntry<TestDescription, Map<Step, Stopwatch>> entryMap
        in stopwatches.entries) {
      for (MapEntry<Step, Stopwatch> entry in entryMap.value.entries) {
        if (entry.value.isRunning) throw "unexpectedly already running";
        entry.value.elapsed + entry.value.elapsed;
        totalRuntimesForSteps[entry.key.name] =
            (totalRuntimesForSteps[entry.key.name] ?? new Duration()) +
                entry.value.elapsed;
      }
    }
    List<MapEntry<String, Duration>> entries =
        totalRuntimesForSteps.entries.toList();
    entries.sort((a, b) => a.value.compareTo(b.value));
    for (MapEntry<String, Duration> entry in entries) {
      const int maxLength = 25;
      String key = (entry.key.length > maxLength)
          ? entry.key.substring(0, maxLength)
          : entry.key.padLeft(maxLength);
      print("$key: ${entry.value} ms");
    }
    super.logSuiteComplete(suite);
  }
}
