// 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 'util.dart';

const _retryInterval = Duration(milliseconds: 200);

/// 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 until all isolates are
/// in the paused state.
///
/// If [includeDart] is true, code coverage for core `dart:*` libraries will be
/// collected.
///
/// 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.
Future<Map<String, dynamic>> collect(Uri serviceUri, bool resume,
    bool waitPaused, bool includeDart, Set<String> scopedOutput,
    {Set<String> isolateIds, Duration timeout}) async {
  scopedOutput ??= <String>{};
  if (serviceUri == null) throw ArgumentError('serviceUri must not be null');

  // 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);

  VmService service;
  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));
      service = VmService(
          controller.stream, (String message) => socket.add(message),
          log: StdoutLog(), disposeHandler: () => socket.close());
      await service.getVM().timeout(_retryInterval);
    } on TimeoutException {
      service.dispose();
      rethrow;
    }
  }, _retryInterval, timeout: timeout);
  try {
    if (waitPaused) {
      await _waitIsolatesPaused(service, timeout: timeout);
    }

    return await _getAllCoverage(
        service, includeDart, scopedOutput, isolateIds);
  } finally {
    if (resume) {
      await _resumeIsolates(service);
    }
    service.dispose();
  }
}

Future<Map<String, dynamic>> _getAllCoverage(VmService service,
    bool includeDart, Set<String> scopedOutput, Set<String> isolateIds) async {
  scopedOutput ??= <String>{};
  final vm = await service.getVM();
  final allCoverage = <Map<String, dynamic>>[];

  for (var isolateRef in vm.isolates) {
    if (isolateIds != null && !isolateIds.contains(isolateRef.id)) continue;
    if (scopedOutput.isNotEmpty) {
      final scripts = await service.getScripts(isolateRef.id);
      for (var script in scripts.scripts) {
        final uri = Uri.parse(script.uri);
        if (uri.scheme != 'package') continue;
        final scope = uri.path.split('/').first;
        // Skip scripts which should not be included in the report.
        if (!scopedOutput.contains(scope)) continue;
        final scriptReport = await service.getSourceReport(
            isolateRef.id, <String>[SourceReportKind.kCoverage],
            forceCompile: true, scriptId: script.id);
        final coverage = await _getCoverageJson(
            service, isolateRef, scriptReport, includeDart);
        allCoverage.addAll(coverage);
      }
    } else {
      final isolateReport = await service.getSourceReport(
        isolateRef.id,
        <String>[SourceReportKind.kCoverage],
        forceCompile: true,
      );
      final coverage = await _getCoverageJson(
          service, isolateRef, isolateReport, includeDart);
      allCoverage.addAll(coverage);
    }
  }
  return <String, dynamic>{'type': 'CodeCoverage', 'coverage': allCoverage};
}

Future _resumeIsolates(VmService service) async {
  final vm = await service.getVM();
  for (var isolateRef in vm.isolates) {
    final isolate = await service.getIsolate(isolateRef.id) as Isolate;
    if (isolate.pauseEvent.kind != EventKind.kResume) {
      await service.resume(isolateRef.id);
    }
  }
}

Future _waitIsolatesPaused(VmService service, {Duration timeout}) async {
  final pauseEvents = <String>{
    EventKind.kPauseStart,
    EventKind.kPauseException,
    EventKind.kPauseExit,
    EventKind.kPauseInterrupted,
    EventKind.kPauseBreakpoint
  };

  Future allPaused() async {
    final vm = await service.getVM();
    for (var isolateRef in vm.isolates) {
      final isolate = await service.getIsolate(isolateRef.id) as Isolate;
      if (!pauseEvents.contains(isolate.pauseEvent.kind)) {
        throw 'Unpaused isolates remaining.';
      }
    }
  }

  return retry(allPaused, _retryInterval, timeout: timeout);
}

/// 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>>> _getCoverageJson(VmService service,
    IsolateRef isolateRef, SourceReport report, bool includeDart) async {
  // script uri -> { line -> hit count }
  final hitMaps = <Uri, Map<int, int>>{};
  final scripts = <ScriptRef, Script>{};
  for (var range in report.ranges) {
    final scriptRef = report.scripts[range.scriptIndex];
    final scriptUri = Uri.parse(report.scripts[range.scriptIndex].uri);

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

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

    if (!scripts.containsKey(scriptRef)) {
      scripts[scriptRef] =
          await service.getObject(isolateRef.id, scriptRef.id) as Script;
    }
    final script = scripts[scriptRef];

    // Look up the hit map for this script (shared across isolates).
    final hitMap = hitMaps.putIfAbsent(scriptUri, () => <int, int>{});

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

    if (coverage == null) continue;

    for (final tokenPos in coverage.hits) {
      final line = _getLineFromTokenPos(script, tokenPos);
      if (line == null) {
        print('tokenPos $tokenPos has no line mapping for script $scriptUri');
      }
      hitMap[line] = hitMap.containsKey(line) ? hitMap[line] + 1 : 1;
    }
    for (final tokenPos in coverage.misses) {
      final line = _getLineFromTokenPos(script, tokenPos);
      if (line == null) {
        print('tokenPos $tokenPos has no line mapping for script $scriptUri');
      }
      hitMap.putIfAbsent(line, () => 0);
    }
  }

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

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

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