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

import 'dart:async';

import 'vm_service_helper.dart' as vmService;

Future<void> main(List<String> args) async {
  CoverageHelper coverageHelper = new CoverageHelper();

  List<String> allArgs = <String>[];
  allArgs.addAll([
    "--disable-dart-dev",
    "--enable-asserts",
    "--pause_isolates_on_exit",
  ]);
  allArgs.addAll(args);

  await coverageHelper.start(allArgs);
}

class CoverageHelper extends vmService.LaunchingVMServiceHelper {
  final bool forceCompilation;
  final bool printHits;

  CoverageHelper({this.forceCompilation: false, this.printHits: true});

  @override
  Future<void> run() async {
    vmService.VM vm = await serviceClient.getVM();
    if (vm.isolates!.length != 1) {
      throw "Expected 1 isolate, got ${vm.isolates!.length}";
    }
    vmService.IsolateRef isolateRef = vm.isolates!.single;
    await waitUntilIsolateIsRunnable(isolateRef.id!);
    await serviceClient.resume(isolateRef.id!);
    Completer<String> cTimeout = new Completer();
    Timer timer = new Timer(new Duration(minutes: 20), () {
      cTimeout.complete("Timeout");
      killProcess();
    });

    Completer<String> cRunDone = new Completer();
    // ignore: unawaited_futures
    waitUntilPaused(isolateRef.id!).then((value) => cRunDone.complete("Done"));

    await Future.any([cRunDone.future, cTimeout.future, cProcessExited.future]);

    timer.cancel();

    if (!await isPausedAtExit(isolateRef.id!)) {
      killProcess();
      throw "Expected to be paused at exit, but is just paused!";
    }

    // Get and process coverage information.
    Stopwatch stopwatch = new Stopwatch()..start();
    vmService.SourceReport sourceReport = await serviceClient.getSourceReport(
        isolateRef.id!, [vmService.SourceReportKind.kCoverage],
        forceCompile: forceCompilation);
    print("Got source report from VM in ${stopwatch.elapsedMilliseconds} ms");
    stopwatch.reset();
    Map<Uri, Coverage> coverages = {};
    for (vmService.SourceReportRange range in sourceReport.ranges!) {
      vmService.ScriptRef script = sourceReport.scripts![range.scriptIndex!];
      Uri scriptUri = Uri.parse(script.uri!);
      if (!includeCoverageFor(scriptUri)) continue;
      Coverage coverage = coverages[scriptUri] ??= new Coverage();

      vmService.SourceReportCoverage? sourceReportCoverage = range.coverage;
      if (sourceReportCoverage == null) {
        // Range not compiled. Record the range if provided.
        assert(!range.compiled!);
        if (range.startPos! >= 0 || range.endPos! >= 0) {
          coverage.notCompiled
              .add(new StartEndPair(range.startPos!, range.endPos!));
        }
        continue;
      }
      coverage.hits.addAll(sourceReportCoverage.hits!);
      coverage.misses.addAll(sourceReportCoverage.misses!);
    }
    print("Processed source report from VM in "
        "${stopwatch.elapsedMilliseconds} ms");
    stopwatch.reset();

    // It's paused at exit, so resuming should allow us to exit.
    await serviceClient.resume(isolateRef.id!);

    for (MapEntry<Uri, Coverage> entry in coverages.entries) {
      assert(entry.value.hits.intersection(entry.value.misses).isEmpty);
      if (entry.value.hits.isEmpty &&
          entry.value.misses.isEmpty &&
          entry.value.notCompiled.isEmpty) {
        continue;
      }
      print(entry.key);
      if (printHits) {
        print("Hits: ${entry.value.hits.toList()..sort()}");
      }
      print("Misses: ${entry.value.misses.toList()..sort()}");
      print("Not compiled: ${entry.value.notCompiled.toList()..sort()}");
      print("");
    }
  }

  Completer<String> cProcessExited = new Completer();
  @override
  void processExited(int exitCode) {
    cProcessExited.complete("Exit");
  }

  bool includeCoverageFor(Uri uri) {
    if (uri.isScheme("dart")) {
      return false;
    }
    if (uri.isScheme("package")) {
      return uri.pathSegments.first == "front_end" ||
          uri.pathSegments.first == "_fe_analyzer_shared" ||
          uri.pathSegments.first == "kernel";
    }
    return true;
  }
}

class Coverage {
  final Set<int> hits = {};
  final Set<int> misses = {};
  final Set<StartEndPair> notCompiled = {};
}

class StartEndPair implements Comparable {
  final int startPos;
  final int endPos;

  StartEndPair(this.startPos, this.endPos);

  @override
  String toString() => "[$startPos - $endPos]";

  @override
  int compareTo(dynamic other) {
    if (other is! StartEndPair) return -1;
    StartEndPair o = other;
    return startPos - o.startPos;
  }
}
