// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:coverage/coverage.dart' as coverage;
import 'package:meta/meta.dart';

import '../base/file_system.dart';
import '../base/io.dart';
import '../base/process.dart';
import '../globals.dart' as globals;
import '../vmservice.dart';

import 'test_device.dart';
import 'test_time_recorder.dart';
import 'watcher.dart';

/// A class that collects code coverage data during test runs.
class CoverageCollector extends TestWatcher {
  CoverageCollector({
      this.libraryNames, this.verbose = true, required this.packagesPath,
      this.resolver, this.testTimeRecorder, this.branchCoverage = false});

  /// True when log messages should be emitted.
  final bool verbose;

  /// The path to the package_config.json of the package for which code
  /// coverage is computed.
  final String packagesPath;

  /// Map of file path to coverage hit map for that file.
  Map<String, coverage.HitMap>? _globalHitmap;

  /// The names of the libraries to gather coverage for. If null, all libraries
  /// will be accepted.
  Set<String>? libraryNames;

  final coverage.Resolver? resolver;
  final Map<String, List<List<int>>?> _ignoredLinesInFilesCache = <String, List<List<int>>?>{};

  final TestTimeRecorder? testTimeRecorder;

  /// Whether to collect branch coverage information.
  bool branchCoverage;

  static Future<coverage.Resolver> getResolver(String? packagesPath) async {
    try {
      return await coverage.Resolver.create(packagesPath: packagesPath);
    } on FileSystemException {
      // When given a bad packages path (as for instance done in some tests)
      // just ignore it and return one without a packages path.
      return coverage.Resolver.create();
    }
  }

  @override
  Future<void> handleFinishedTest(TestDevice testDevice) async {
    _logMessage('Starting coverage collection');
    await collectCoverage(testDevice);
  }

  void _logMessage(String line, { bool error = false }) {
    if (!verbose) {
      return;
    }
    if (error) {
      globals.printError(line);
    } else {
      globals.printTrace(line);
    }
  }

  void _addHitmap(Map<String, coverage.HitMap> hitmap) {
    final Stopwatch? stopwatch = testTimeRecorder?.start(TestTimePhases.CoverageAddHitmap);
    if (_globalHitmap == null) {
      _globalHitmap = hitmap;
    } else {
      _globalHitmap!.merge(hitmap);
    }
    testTimeRecorder?.stop(TestTimePhases.CoverageAddHitmap, stopwatch!);
  }

  /// The directory of the package for which coverage is being collected.
  String get packageDirectory {
    // The coverage package expects the directory of the package itself, and
    // uses that to locate the package_info.json file, which it treats as a
    // private implementation detail. In general, the package_info.json file is
    // located in `.dart_tool/package_info.json` relative to the package
    // directory, so we return the grandparent directory of that file.
    //
    // This may not be a safe assumption in non-standard environments, such as
    // when building under build systems such as Bazel. In those cases, this
    // getter should be overridden.
    return globals.fs.directory(globals.fs.file(packagesPath).dirname).dirname;
  }

  /// Collects coverage for an isolate using the given `port`.
  ///
  /// This should be called when the code whose coverage data is being collected
  /// has been run to completion so that all coverage data has been recorded.
  ///
  /// The returned [Future] completes when the coverage is collected.
  Future<void> collectCoverageIsolate(Uri observatoryUri) async {
    _logMessage('collecting coverage data from $observatoryUri...');
    final Map<String, dynamic> data = await collect(
        observatoryUri, libraryNames, branchCoverage: branchCoverage);

    _logMessage('($observatoryUri): collected coverage data; merging...');
    _addHitmap(await coverage.HitMap.parseJson(
      data['coverage'] as List<Map<String, dynamic>>,
      packagePath: packageDirectory,
      checkIgnoredLines: true,
    ));
    _logMessage('($observatoryUri): done merging coverage data into global coverage map.');
  }

  /// Collects coverage for the given [Process] using the given `port`.
  ///
  /// This should be called when the code whose coverage data is being collected
  /// has been run to completion so that all coverage data has been recorded.
  ///
  /// The returned [Future] completes when the coverage is collected.
  Future<void> collectCoverage(TestDevice testDevice, {
    @visibleForTesting FlutterVmService? serviceOverride,
  }) async {
    final Stopwatch? totalTestTimeRecorderStopwatch = testTimeRecorder?.start(TestTimePhases.CoverageTotal);

    late Map<String, dynamic> data;

    final Stopwatch? collectTestTimeRecorderStopwatch = testTimeRecorder?.start(TestTimePhases.CoverageCollect);

    final Future<void> processComplete = testDevice.finished.catchError(
      (Object error) => throw Exception(
          'Failed to collect coverage, test device terminated prematurely with '
          'error: ${(error as TestDeviceException).message}.'),
      test: (Object error) => error is TestDeviceException,
    );

    final Future<void> collectionComplete = testDevice.observatoryUri
      .then((Uri? observatoryUri) {
        _logMessage('collecting coverage data from $testDevice at $observatoryUri...');
        return collect(
            observatoryUri!, libraryNames, serviceOverride: serviceOverride,
            branchCoverage: branchCoverage)
          .then<void>((Map<String, dynamic> result) {
            _logMessage('Collected coverage data.');
            data = result;
          });
      });

    await Future.any<void>(<Future<void>>[ processComplete, collectionComplete ]);

    testTimeRecorder?.stop(TestTimePhases.CoverageCollect, collectTestTimeRecorderStopwatch!);

    _logMessage('Merging coverage data...');
    final Stopwatch? parseTestTimeRecorderStopwatch = testTimeRecorder?.start(TestTimePhases.CoverageParseJson);

   final Map<String, coverage.HitMap> hitmap = coverage.HitMap.parseJsonSync(
        data['coverage'] as List<Map<String, dynamic>>,
        checkIgnoredLines: true,
        resolver: resolver ?? await CoverageCollector.getResolver(packageDirectory),
        ignoredLinesInFilesCache: _ignoredLinesInFilesCache);
    testTimeRecorder?.stop(TestTimePhases.CoverageParseJson, parseTestTimeRecorderStopwatch!);

    _addHitmap(hitmap);
    _logMessage('Done merging coverage data into global coverage map.');
    testTimeRecorder?.stop(TestTimePhases.CoverageTotal, totalTestTimeRecorderStopwatch!);
  }

  /// Returns formatted coverage data once all coverage data has been collected.
  ///
  /// This will not start any collection tasks. It us up to the caller of to
  /// call [collectCoverage] for each process first.
  Future<String?> finalizeCoverage({
    String Function(Map<String, coverage.HitMap> hitmap)? formatter,
    coverage.Resolver? resolver,
    Directory? coverageDirectory,
  }) async {
    if (_globalHitmap == null) {
      return null;
    }
    if (formatter == null) {
      final coverage.Resolver usedResolver = resolver ?? this.resolver ?? await CoverageCollector.getResolver(packagesPath);
      final String packagePath = globals.fs.currentDirectory.path;
      final List<String> reportOn = coverageDirectory == null
          ? <String>[globals.fs.path.join(packagePath, 'lib')]
          : <String>[coverageDirectory.path];
      formatter = (Map<String, coverage.HitMap> hitmap) => hitmap
          .formatLcov(usedResolver, reportOn: reportOn, basePath: packagePath);
    }
    final String result = formatter(_globalHitmap!);
    _globalHitmap = null;
    return result;
  }

  Future<bool> collectCoverageData(String? coveragePath, { bool mergeCoverageData = false, Directory? coverageDirectory }) async {
    final String? coverageData = await finalizeCoverage(
      coverageDirectory: coverageDirectory,
    );
    _logMessage('coverage information collection complete');
    if (coverageData == null) {
      return false;
    }

    final File coverageFile = globals.fs.file(coveragePath)
      ..createSync(recursive: true)
      ..writeAsStringSync(coverageData, flush: true);
    _logMessage('wrote coverage data to $coveragePath (size=${coverageData.length})');

    const String baseCoverageData = 'coverage/lcov.base.info';
    if (mergeCoverageData) {
      if (!globals.fs.isFileSync(baseCoverageData)) {
        _logMessage('Missing "$baseCoverageData". Unable to merge coverage data.', error: true);
        return false;
      }

      if (globals.os.which('lcov') == null) {
        String installMessage = 'Please install lcov.';
        if (globals.platform.isLinux) {
          installMessage = 'Consider running "sudo apt-get install lcov".';
        } else if (globals.platform.isMacOS) {
          installMessage = 'Consider running "brew install lcov".';
        }
        _logMessage('Missing "lcov" tool. Unable to merge coverage data.\n$installMessage', error: true);
        return false;
      }

      final Directory tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_tools_test_coverage.');
      try {
        final File sourceFile = coverageFile.copySync(globals.fs.path.join(tempDir.path, 'lcov.source.info'));
        final RunResult result = globals.processUtils.runSync(<String>[
          'lcov',
          '--add-tracefile', baseCoverageData,
          '--add-tracefile', sourceFile.path,
          '--output-file', coverageFile.path,
        ]);
        if (result.exitCode != 0) {
          return false;
        }
      } finally {
        tempDir.deleteSync(recursive: true);
      }
    }
    return true;
  }

  @override
  Future<void> handleTestCrashed(TestDevice testDevice) async { }

  @override
  Future<void> handleTestTimedOut(TestDevice testDevice) async { }
}

Future<Map<String, dynamic>> collect(Uri serviceUri, Set<String>? libraryNames, {
  bool waitPaused = false,
  String? debugName,
  @visibleForTesting bool forceSequential = false,
  @visibleForTesting FlutterVmService? serviceOverride,
  bool branchCoverage = false,
}) {
  return coverage.collect(
      serviceUri, false, false, false, libraryNames,
      serviceOverrideForTesting: serviceOverride?.service,
      branchCoverage: branchCoverage);
}
