// Copyright (c) 2014, 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.

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

import 'package:vm_service/vm_service.dart';

import 'hitmap.dart';
import 'isolate_paused_listener.dart';
import 'util.dart';

const _retryInterval = Duration(milliseconds: 200);
const _debugTokenPositions = bool.fromEnvironment('DEBUG_COVERAGE');

/// Collects coverage for all isolates in the running VM.
///
/// Collects a hit-map containing merged coverage for all isolates in the Dart
/// VM associated with the specified [serviceUri]. Returns a map suitable for
/// input to the coverage formatters that ship with this package.
///
/// [serviceUri] must specify the http/https URI of the service port of a
/// running Dart VM and must not be null.
///
/// If [resume] is true, all isolates will be resumed once coverage collection
/// is complete.
///
/// If [waitPaused] is true, collection will not begin for an isolate until it
/// is in the paused state.
///
/// If [includeDart] is true, code coverage for core `dart:*` libraries will be
/// collected.
///
/// If [functionCoverage] is true, function coverage information will be
/// collected.
///
/// If [branchCoverage] is true, branch coverage information will be collected.
/// This will only work correctly if the target VM was run with the
/// --branch-coverage flag.
///
/// If [scopedOutput] is non-empty, coverage will be restricted so that only
/// scripts that start with any of the provided paths are considered.
///
/// If [isolateIds] is set, the coverage gathering will be restricted to only
/// those VM isolates.
///
/// If [coverableLineCache] is set, the collector will avoid recompiling
/// libraries it has already seen (see VmService.getSourceReport's
/// librariesAlreadyCompiled parameter). This is only useful when doing more
/// than one [collect] call over the same libraries. Pass an empty map to the
/// first call, and then pass the same map to all subsequent calls.
///
/// [serviceOverrideForTesting] is for internal testing only, and should not be
/// set by users.
Future<Map<String, dynamic>> collect(Uri serviceUri, bool resume,
    bool waitPaused, bool includeDart, Set<String>? scopedOutput,
    {Set<String>? isolateIds,
    Duration? timeout,
    bool functionCoverage = false,
    bool branchCoverage = false,
    Map<String, Set<int>>? coverableLineCache,
    VmService? serviceOverrideForTesting}) async {
  scopedOutput ??= <String>{};

  late VmService service;
  if (serviceOverrideForTesting != null) {
    service = serviceOverrideForTesting;
  } else {
    // Create websocket URI. Handle any trailing slashes.
    final pathSegments =
        serviceUri.pathSegments.where((c) => c.isNotEmpty).toList()..add('ws');
    final uri = serviceUri.replace(scheme: 'ws', pathSegments: pathSegments);

    await retry(() async {
      try {
        final options = const CompressionOptions(enabled: false);
        final socket = await WebSocket.connect('$uri', compression: options);
        final controller = StreamController<String>();
        socket.listen((data) => controller.add(data as String), onDone: () {
          controller.close();
          service.dispose();
        });
        service = VmService(controller.stream, socket.add,
            log: StdoutLog(), disposeHandler: socket.close);
        await service.getVM().timeout(_retryInterval);
      } on TimeoutException {
        // The signature changed in vm_service version 6.0.0.
        // ignore: await_only_futures
        await service.dispose();
        rethrow;
      }
    }, _retryInterval, timeout: timeout);
  }

  try {
    return await _getAllCoverage(
        service,
        includeDart,
        functionCoverage,
        branchCoverage,
        scopedOutput,
        isolateIds,
        coverableLineCache,
        waitPaused);
  } finally {
    if (resume && !waitPaused) {
      await _resumeIsolates(service);
    }
    // The signature changed in vm_service version 6.0.0.
    // ignore: await_only_futures
    await service.dispose();
  }
}

Future<Map<String, dynamic>> _getAllCoverage(
    VmService service,
    bool includeDart,
    bool functionCoverage,
    bool branchCoverage,
    Set<String> scopedOutput,
    Set<String>? isolateIds,
    Map<String, Set<int>>? coverableLineCache,
    bool waitPaused) async {
  final allCoverage = <Map<String, dynamic>>[];

  final sourceReportKinds = [
    SourceReportKind.kCoverage,
    if (branchCoverage) SourceReportKind.kBranchCoverage,
  ];

  final librariesAlreadyCompiled = coverableLineCache?.keys.toList();

  // Program counters are shared between isolates in the same group. So we need
  // to make sure we're only gathering coverage data for one isolate in each
  // group, otherwise we'll double count the hits.
  final coveredIsolateGroups = <String>{};

  Future<void> collectIsolate(IsolateRef isolateRef) async {
    if (!(isolateIds?.contains(isolateRef.id) ?? true)) return;

    // coveredIsolateGroups is only relevant for the !waitPaused flow. The
    // waitPaused flow achieves the same once-per-group behavior using the
    // isLastIsolateInGroup flag.
    final isolateGroupId = isolateRef.isolateGroupId;
    if (isolateGroupId != null) {
      if (coveredIsolateGroups.contains(isolateGroupId)) return;
      coveredIsolateGroups.add(isolateGroupId);
    }

    late final SourceReport isolateReport;
    try {
      isolateReport = await service.getSourceReport(
        isolateRef.id!,
        sourceReportKinds,
        forceCompile: true,
        reportLines: true,
        libraryFilters: scopedOutput.isNotEmpty
            ? List.from(scopedOutput.map((filter) => 'package:$filter/'))
            : null,
        librariesAlreadyCompiled: librariesAlreadyCompiled,
      );
    } on SentinelException {
      return;
    }

    final coverage = await _processSourceReport(
        service,
        isolateRef,
        isolateReport,
        includeDart,
        functionCoverage,
        branchCoverage,
        coverableLineCache,
        scopedOutput);
    allCoverage.addAll(coverage);
  }

  if (waitPaused) {
    await IsolatePausedListener(service,
            (IsolateRef isolateRef, bool isLastIsolateInGroup) async {
      if (isLastIsolateInGroup) {
        await collectIsolate(isolateRef);
      }
    }, stderr.writeln)
        .waitUntilAllExited();
  } else {
    for (final isolateRef in await getAllIsolates(service)) {
      await collectIsolate(isolateRef);
    }
  }

  return <String, dynamic>{'type': 'CodeCoverage', 'coverage': allCoverage};
}

Future _resumeIsolates(VmService service) async {
  final vm = await service.getVM();
  final futures = <Future>[];
  for (var isolateRef in vm.isolates!) {
    // Guard against sync as well as async errors: sync - when we are writing
    // message to the socket, the socket might be closed; async - when we are
    // waiting for the response, the socket again closes.
    futures.add(Future.sync(() async {
      final isolate = await service.getIsolate(isolateRef.id!);
      if (isolate.pauseEvent!.kind != EventKind.kResume) {
        await service.resume(isolateRef.id!);
      }
    }));
  }
  try {
    await Future.wait(futures);
  } catch (_) {
    // Ignore resume isolate failures
  }
}

/// Returns the line number to which the specified token position maps.
///
/// Performs a binary search within the script's token position table to locate
/// the line in question.
int? _getLineFromTokenPos(Script script, int tokenPos) {
  // TODO(cbracken): investigate whether caching this lookup results in
  // significant performance gains.
  var min = 0;
  var max = script.tokenPosTable!.length;
  while (min < max) {
    final mid = min + ((max - min) >> 1);
    final row = script.tokenPosTable![mid];
    if (row[1] > tokenPos) {
      max = mid;
    } else {
      for (var i = 1; i < row.length; i += 2) {
        if (row[i] == tokenPos) return row.first;
      }
      min = mid + 1;
    }
  }
  return null;
}

/// Returns a JSON coverage list backward-compatible with pre-1.16.0 SDKs.
Future<List<Map<String, dynamic>>> _processSourceReport(
    VmService service,
    IsolateRef isolateRef,
    SourceReport report,
    bool includeDart,
    bool functionCoverage,
    bool branchCoverage,
    Map<String, Set<int>>? coverableLineCache,
    Set<String> scopedOutput) async {
  final hitMaps = <Uri, HitMap>{};
  final scripts = <ScriptRef, Script>{};
  final libraries = <LibraryRef>{};
  final needScripts = functionCoverage;

  Future<Script?> getScript(ScriptRef? scriptRef) async {
    if (scriptRef == null) {
      return null;
    }
    if (!scripts.containsKey(scriptRef)) {
      scripts[scriptRef] =
          await service.getObject(isolateRef.id!, scriptRef.id!) as Script;
    }
    return scripts[scriptRef];
  }

  HitMap getHitMap(Uri scriptUri) => hitMaps.putIfAbsent(
      scriptUri,
      () => HitMap.empty(
          functionCoverage: functionCoverage, branchCoverage: branchCoverage));

  Future<void> processFunction(FuncRef funcRef) async {
    final func = await service.getObject(isolateRef.id!, funcRef.id!) as Func;
    if ((func.implicit ?? false) || (func.isAbstract ?? false)) {
      return;
    }
    final location = func.location;
    if (location == null) {
      return;
    }
    final script = await getScript(location.script);
    if (script == null) {
      return;
    }
    final funcName = await _getFuncName(service, isolateRef, func);
    // TODO(liama): Is this still necessary, or is location.line valid?
    final tokenPos = location.tokenPos!;
    final line = _getLineFromTokenPos(script, tokenPos);
    if (line == null) {
      if (_debugTokenPositions) {
        stderr.writeln(
            'tokenPos $tokenPos in function ${funcRef.name} has no line '
            'mapping for script ${script.uri!}');
      }
      return;
    }
    final hits = getHitMap(Uri.parse(script.uri!));
    hits.funcNames![line] = funcName;
  }

  for (var range in report.ranges!) {
    final scriptRef = report.scripts![range.scriptIndex!];
    final scriptUriString = scriptRef.uri;
    if (!scopedOutput.includesScript(scriptUriString)) {
      // Sometimes a range's script can be different to the function's script
      // (eg mixins), so we have to re-check the scope filter.
      // See https://github.com/dart-lang/tools/issues/530
      continue;
    }
    final scriptUri = Uri.parse(scriptUriString!);

    // If we have a coverableLineCache, use it in the same way we use
    // SourceReportCoverage.misses: to add zeros to the coverage result for all
    // the lines that don't have a hit. Afterwards, add all the lines that were
    // hit or missed to the cache, so that the next coverage collection won't
    // need to compile this library.
    final coverableLines =
        coverableLineCache?.putIfAbsent(scriptUriString, () => <int>{});

    // Not returned in scripts section of source report.
    if (scriptUri.scheme == 'evaluate') continue;

    // Skip scripts from dart:.
    if (!includeDart && scriptUri.scheme == 'dart') continue;

    // Look up the hit maps for this script (shared across isolates).
    final hits = getHitMap(scriptUri);

    Script? script;
    if (needScripts) {
      script = await getScript(scriptRef);
      if (script == null) continue;
    }

    // If the script's library isn't loaded, load it then look up all its funcs.
    final libRef = script?.library;
    if (functionCoverage && libRef != null && !libraries.contains(libRef)) {
      libraries.add(libRef);
      final library =
          await service.getObject(isolateRef.id!, libRef.id!) as Library;
      if (library.functions != null) {
        for (var funcRef in library.functions!) {
          await processFunction(funcRef);
        }
      }
      if (library.classes != null) {
        for (var classRef in library.classes!) {
          final clazz =
              await service.getObject(isolateRef.id!, classRef.id!) as Class;
          if (clazz.functions != null) {
            for (var funcRef in clazz.functions!) {
              await processFunction(funcRef);
            }
          }
        }
      }
    }

    // Collect hits and misses.
    final coverage = range.coverage;

    if (coverage == null) continue;

    void forEachLine(List<int>? tokenPositions, void Function(int line) body) {
      if (tokenPositions == null) return;
      for (final line in tokenPositions) {
        body(line);
      }
    }

    if (coverableLines != null) {
      for (final line in coverableLines) {
        hits.lineHits.putIfAbsent(line, () => 0);
      }
    }

    forEachLine(coverage.hits, (line) {
      hits.lineHits.increment(line);
      coverableLines?.add(line);
      if (hits.funcNames != null && hits.funcNames!.containsKey(line)) {
        hits.funcHits!.increment(line);
      }
    });
    forEachLine(coverage.misses, (line) {
      hits.lineHits.putIfAbsent(line, () => 0);
      coverableLines?.add(line);
    });
    hits.funcNames?.forEach((line, funcName) {
      hits.funcHits?.putIfAbsent(line, () => 0);
    });

    final branches = range.branchCoverage;
    if (branchCoverage && branches != null) {
      forEachLine(branches.hits, (line) {
        hits.branchHits!.increment(line);
      });
      forEachLine(branches.misses, (line) {
        hits.branchHits!.putIfAbsent(line, () => 0);
      });
    }
  }

  // Output JSON
  final coverage = <Map<String, dynamic>>[];
  hitMaps.forEach((uri, hits) {
    coverage.add(hitmapToJson(hits, uri));
  });
  return coverage;
}

extension _MapExtension<T> on Map<T, int> {
  void increment(T key) => this[key] = (this[key] ?? 0) + 1;
}

Future<String> _getFuncName(
    VmService service, IsolateRef isolateRef, Func func) async {
  if (func.name == null) {
    return '${func.type}:${func.location!.tokenPos}';
  }
  final owner = func.owner;
  if (owner is ClassRef) {
    final cls = await service.getObject(isolateRef.id!, owner.id!) as Class;
    if (cls.name != null) return '${cls.name}.${func.name}';
  }
  return func.name!;
}

class StdoutLog extends Log {
  @override
  void warning(String message) => print(message);

  @override
  void severe(String message) => print(message);
}

extension _ScopedOutput on Set<String> {
  bool includesScript(String? scriptUriString) {
    if (scriptUriString == null) return false;

    // If the set is empty, it means the user didn't specify a --scope-output
    // flag, so allow everything.
    if (isEmpty) return true;

    final scriptUri = Uri.parse(scriptUriString);
    if (scriptUri.scheme != 'package') return false;

    final scope = scriptUri.pathSegments.first;
    return contains(scope);
  }
}
