// Copyright (c) 2015, 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:convert';

import 'package:coverage/coverage.dart';
import 'package:coverage/src/util.dart';
import 'package:path/path.dart' as p;
import 'package:test/test.dart';

import 'test_util.dart';

final _isolateLibPath = p.join('test', 'test_files', 'test_app_isolate.dart');

final _sampleAppFileUri = p.toUri(p.absolute(testAppPath)).toString();
final _isolateLibFileUri = p.toUri(p.absolute(_isolateLibPath)).toString();

void main() {
  test('collect_coverage_api', () async {
    final json = await _collectCoverage();
    expect(json.keys, unorderedEquals(<String>['type', 'coverage']));
    expect(json, containsPair('type', 'CodeCoverage'));

    final coverage = json['coverage'] as List;
    expect(coverage, isNotEmpty);

    final sources = coverage.cast<Map>().fold(<String, List<Map>>{},
        (Map<String, List<Map>> map, value) {
      final sourceUri = value['source'] as String;
      map.putIfAbsent(sourceUri, () => <Map>[]).add(value);
      return map;
    });

    for (var sampleCoverageData in sources[_sampleAppFileUri]!) {
      expect(sampleCoverageData['hits'], isNotEmpty);
    }

    for (var sampleCoverageData in sources[_isolateLibFileUri]!) {
      expect(sampleCoverageData['hits'], isNotEmpty);
    }
  });

  test('collect_coverage_api with scoped output', () async {
    final json =
        await _collectCoverage(scopedOutput: <String>{}..add('coverage'));
    expect(json.keys, unorderedEquals(<String>['type', 'coverage']));
    expect(json, containsPair('type', 'CodeCoverage'));

    final coverage = json['coverage'] as List;
    expect(coverage, isNotEmpty);

    final sources = coverage.fold(<String, dynamic>{},
        (Map<String, dynamic> map, dynamic value) {
      final sourceUri = value['source'] as String;
      map.putIfAbsent(sourceUri, () => <Map>[]).add(value);
      return map;
    });

    for (var key in sources.keys) {
      final uri = Uri.parse(key);
      expect(uri.path.startsWith('coverage'), isTrue);
    }
  });

  test('collect_coverage_api with isolateIds', () async {
    final json = await _collectCoverage(isolateIds: true);
    expect(json.keys, unorderedEquals(<String>['type', 'coverage']));
    expect(json, containsPair('type', 'CodeCoverage'));

    final coverage = json['coverage'] as List<Map<String, dynamic>>;
    expect(coverage, isNotEmpty);

    final testAppCoverage = _getScriptCoverage(coverage, 'test_app.dart')!;
    var hits = testAppCoverage['hits'] as List<int>;
    _expectHitCount(hits, 46, 0);
    _expectHitCount(hits, 50, 0);

    final isolateCoverage =
        _getScriptCoverage(coverage, 'test_app_isolate.dart')!;
    hits = isolateCoverage['hits'] as List<int>;
    _expectHitCount(hits, 11, 1);
    _expectHitCount(hits, 28, 1);
  });

  test('collect_coverage_api with function coverage', () async {
    final json = await _collectCoverage(functionCoverage: true);
    expect(json.keys, unorderedEquals(<String>['type', 'coverage']));
    expect(json, containsPair('type', 'CodeCoverage'));

    final coverage = json['coverage'] as List;
    expect(coverage, isNotEmpty);

    final sources = coverage.cast<Map>().fold(<String, List<Map>>{},
        (Map<String, List<Map>> map, value) {
      final sourceUri = value['source'] as String;
      map.putIfAbsent(sourceUri, () => <Map>[]).add(value);
      return map;
    });

    for (var sampleCoverageData in sources[_sampleAppFileUri]!) {
      expect(sampleCoverageData['funcNames'], isNotEmpty);
      expect(sampleCoverageData['funcHits'], isNotEmpty);
    }

    for (var sampleCoverageData in sources[_isolateLibFileUri]!) {
      expect(sampleCoverageData['funcNames'], isNotEmpty);
      expect(sampleCoverageData['funcHits'], isNotEmpty);
    }
  });
}

Future<Map<String, dynamic>> _collectCoverage(
    {Set<String> scopedOutput = const {},
    bool isolateIds = false,
    bool functionCoverage = false}) async {
  final openPort = await getOpenPort();

  // run the sample app, with the right flags
  final sampleProcess = await runTestApp(openPort);

  // Capture the VM service URI.
  final serviceUriCompleter = Completer<Uri>();
  final isolateIdCompleter = Completer<String>();
  sampleProcess.stdout
      .transform(utf8.decoder)
      .transform(LineSplitter())
      .listen((line) {
    if (!serviceUriCompleter.isCompleted) {
      final serviceUri = extractObservatoryUri(line);
      if (serviceUri != null) {
        serviceUriCompleter.complete(serviceUri);
      }
    }
    if (line.contains('isolateId = ')) {
      isolateIdCompleter.complete(line.split(' = ')[1]);
    }
  });

  final serviceUri = await serviceUriCompleter.future;
  final isolateId = await isolateIdCompleter.future;
  final isolateIdSet = isolateIds ? {isolateId} : null;

  return collect(serviceUri, true, true, false, scopedOutput,
      timeout: timeout,
      isolateIds: isolateIdSet,
      functionCoverage: functionCoverage);
}

// Returns the first coverage hitmap for the script with with the specified
// script filename, ignoring leading path.
Map<String, dynamic>? _getScriptCoverage(
    List<Map<String, dynamic>> coverage, String filename) {
  for (var isolateCoverage in coverage) {
    final script = Uri.parse(isolateCoverage['script']['uri'] as String);
    if (script.pathSegments.last == filename) {
      return isolateCoverage;
    }
  }
  return null;
}

/// Tests that the specified hitmap has the specified hit count for the
/// specified line.
void _expectHitCount(List<int> hits, int line, int hitCount) {
  final hitIndex = hits.indexOf(line);
  if (hitIndex < 0) {
    fail('No hit count for line $line');
  }
  final actual = hits[hitIndex + 1];
  expect(actual, equals(hitCount),
      reason: 'Expected line $line to have $hitCount hits, but found $actual.');
}
