// 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:convert' show json;
import 'dart:io';

import 'resolver.dart';
import 'util.dart';

/// Contains line and function hit information for a single script.
class HitMap {
  /// Constructs a HitMap.
  HitMap([
    Map<int, int>? lineHits,
    this.funcHits,
    this.funcNames,
    this.branchHits,
  ]) : lineHits = lineHits ?? {};

  /// Constructs an empty hitmap, optionally with function and branch coverage
  /// tables.
  HitMap.empty({bool functionCoverage = false, bool branchCoverage = false})
    : this(
        null,
        functionCoverage ? <int, int>{} : null,
        functionCoverage ? <int, String>{} : null,
        branchCoverage ? <int, int>{} : null,
      );

  /// Map from line to hit count for that line.
  final Map<int, int> lineHits;

  /// Map from the first line of each function, to the hit count for that
  /// function. Null if function coverage info was not gathered.
  Map<int, int>? funcHits;

  /// Map from the first line of each function, to the function name. Null if
  /// function coverage info was not gathered.
  Map<int, String>? funcNames;

  /// Map from branch line, to the hit count for that branch. Null if branch
  /// coverage info was not gathered.
  Map<int, int>? branchHits;

  /// Creates a single hitmap from a raw json object.
  ///
  /// Note that when [checkIgnoredLines] is `true` all files will be
  /// read to get ignore comments. This will add some overhead.
  /// To combat this when calling this function multiple times from the
  /// same source (e.g. test runs of different files) a cache is taken
  /// via [ignoredLinesInFilesCache]. If this cache contains the parsed
  /// data for the specific file already, the file will not be read and
  /// parsed again.
  ///
  /// Throws away all entries that are not resolvable.
  static Map<String, HitMap> parseJsonSync(
    List<Map<String, dynamic>> jsonResult, {
    required bool checkIgnoredLines,
    required Map<String, List<List<int>>?> ignoredLinesInFilesCache,
    required Resolver resolver,
  }) {
    // Map of source file to map of line to hit count for that line.
    final globalHitMap = <String, HitMap>{};

    for (var e in jsonResult) {
      final source = e['source'] as String?;
      if (source == null) {
        // Couldn't resolve import, so skip this entry.
        continue;
      }

      void addToMap(Map<int, int> map, int line, int count) {
        final oldCount = map.putIfAbsent(line, () => 0);
        map[line] = count + oldCount;
      }

      void fillHitMap(List hits, Map<int, int> hitMap) {
        // Ignore line annotations require hits to be sorted.
        hits = _sortHits(hits);
        // hits is a flat array of the following format:
        // [ <line|linerange>, <hitcount>,...]
        // line: number.
        // linerange: '<line>-<line>'.
        for (var i = 0; i < hits.length; i += 2) {
          final k = hits[i];
          if (k is int) {
            // Single line.
            addToMap(hitMap, k, hits[i + 1] as int);
          } else if (k is String) {
            // Linerange. We expand line ranges to actual lines at this point.
            final splitPos = k.indexOf('-');
            final start = int.parse(k.substring(0, splitPos));
            final end = int.parse(k.substring(splitPos + 1));
            for (var j = start; j <= end; j++) {
              addToMap(hitMap, j, hits[i + 1] as int);
            }
          } else {
            throw StateError('Expected value of type int or String');
          }
        }
      }

      final sourceHitMap = globalHitMap.putIfAbsent(source, HitMap.new);
      fillHitMap(e['hits'] as List, sourceHitMap.lineHits);
      if (e.containsKey('funcHits')) {
        sourceHitMap.funcHits ??= <int, int>{};
        fillHitMap(e['funcHits'] as List, sourceHitMap.funcHits!);
      }
      if (e.containsKey('funcNames')) {
        sourceHitMap.funcNames ??= <int, String>{};
        final funcNames = e['funcNames'] as List;
        for (var i = 0; i < funcNames.length; i += 2) {
          sourceHitMap.funcNames![funcNames[i] as int] =
              funcNames[i + 1] as String;
        }
      }
      if (e.containsKey('branchHits')) {
        sourceHitMap.branchHits ??= <int, int>{};
        fillHitMap(e['branchHits'] as List, sourceHitMap.branchHits!);
      }
    }
    return checkIgnoredLines
        ? globalHitMap.filterIgnored(
            ignoredLinesInFilesCache: ignoredLinesInFilesCache,
            resolver: resolver,
          )
        : globalHitMap;
  }

  /// Creates a single hitmap from a raw json object.
  ///
  /// Throws away all entries that are not resolvable.
  static Future<Map<String, HitMap>> parseJson(
    List<Map<String, dynamic>> jsonResult, {
    bool checkIgnoredLines = false,
    @Deprecated('Use packagePath') String? packagesPath,
    String? packagePath,
  }) async {
    final resolver = await Resolver.create(
      packagesPath: packagesPath,
      packagePath: packagePath,
    );
    return parseJsonSync(
      jsonResult,
      checkIgnoredLines: checkIgnoredLines,
      ignoredLinesInFilesCache: {},
      resolver: resolver,
    );
  }

  /// Generates a merged hitmap from a set of coverage JSON files.
  static Future<Map<String, HitMap>> parseFiles(
    Iterable<File> files, {
    bool checkIgnoredLines = false,
    @Deprecated('Use packagePath') String? packagesPath,
    String? packagePath,
  }) async {
    final globalHitmap = <String, HitMap>{};
    for (var file in files) {
      final contents = file.readAsStringSync();
      final jsonMap = json.decode(contents) as Map<String, dynamic>;
      if (jsonMap.containsKey('coverage')) {
        final jsonResult = jsonMap['coverage'] as List;
        globalHitmap.merge(
          await HitMap.parseJson(
            jsonResult.cast<Map<String, dynamic>>(),
            checkIgnoredLines: checkIgnoredLines,
            // ignore: deprecated_member_use_from_same_package
            packagesPath: packagesPath,
            packagePath: packagePath,
          ),
        );
      }
    }
    return globalHitmap;
  }
}

extension FileHitMaps on Map<String, HitMap> {
  /// Merges [newMap] into this one.
  void merge(Map<String, HitMap> newMap) {
    newMap.forEach((file, v) {
      final fileResult = this[file];
      if (fileResult != null) {
        _mergeHitCounts(v.lineHits, fileResult.lineHits);
        if (v.funcHits != null) {
          fileResult.funcHits ??= <int, int>{};
          _mergeHitCounts(v.funcHits!, fileResult.funcHits!);
        }
        if (v.funcNames != null) {
          fileResult.funcNames ??= <int, String>{};
          v.funcNames?.forEach((line, name) {
            fileResult.funcNames![line] = name;
          });
        }
        if (v.branchHits != null) {
          fileResult.branchHits ??= <int, int>{};
          _mergeHitCounts(v.branchHits!, fileResult.branchHits!);
        }
      } else {
        this[file] = v;
      }
    });
  }

  static void _mergeHitCounts(Map<int, int> src, Map<int, int> dest) {
    src.forEach((line, count) {
      final lineFileResult = dest[line];
      if (lineFileResult == null) {
        dest[line] = count;
      } else {
        dest[line] = lineFileResult + count;
      }
    });
  }

  /// Filters out lines that are ignored by ignore comments.
  Map<String, HitMap> filterIgnored({
    required Map<String, List<List<int>>?> ignoredLinesInFilesCache,
    required Resolver resolver,
  }) {
    final loader = Loader();
    final newHitMaps = <String, HitMap>{};
    for (final MapEntry(key: source, value: hitMap) in entries) {
      final ignoredLinesList = ignoredLinesInFilesCache.putIfAbsent(source, () {
        final path = resolver.resolve(source);
        if (path == null) return <List<int>>[];
        return getIgnoredLines(path, loader.loadSync(path));
      });
      // Null here means that the whole file is ignored.
      if (ignoredLinesList == null) continue;

      Map<int, int>? filterHits(Map<int, int>? hits) => hits == null
          ? null
          : {
              for (final MapEntry(key: line, value: count) in hits.entries)
                if (!ignoredLinesList.ignoredContains(line)) line: count,
            };

      newHitMaps[source] = HitMap(
        filterHits(hitMap.lineHits),
        filterHits(hitMap.funcHits),
        hitMap.funcNames,
        filterHits(hitMap.branchHits),
      );
    }
    return newHitMaps;
  }
}

/// Class containing information about a coverage hit.
class _HitInfo {
  _HitInfo(this.firstLine, this.hitRange, this.hitCount);

  /// The line number of the first line of this hit range.
  final int firstLine;

  /// A hit range is either a number (1 line) or a String of the form
  /// "start-end" (multi-line range).
  final dynamic hitRange;

  /// How many times this hit range was executed.
  final int hitCount;
}

/// Creates a single hitmap from a raw json object.
///
/// Throws away all entries that are not resolvable.
@Deprecated('Migrate to HitMap.parseJson')
Future<Map<String, Map<int, int>>> createHitmap(
  List<Map<String, dynamic>> jsonResult, {
  bool checkIgnoredLines = false,
  @Deprecated('Use packagePath') String? packagesPath,
  String? packagePath,
}) async {
  final result = await HitMap.parseJson(
    jsonResult,
    checkIgnoredLines: checkIgnoredLines,
    packagesPath: packagesPath,
    packagePath: packagePath,
  );
  return result.map((key, value) => MapEntry(key, value.lineHits));
}

/// Merges [newMap] into [result].
@Deprecated('Migrate to FileHitMaps.merge')
void mergeHitmaps(
  Map<String, Map<int, int>> newMap,
  Map<String, Map<int, int>> result,
) {
  newMap.forEach((file, v) {
    final fileResult = result[file];
    if (fileResult != null) {
      v.forEach((line, count) {
        final lineFileResult = fileResult[line];
        if (lineFileResult == null) {
          fileResult[line] = count;
        } else {
          fileResult[line] = lineFileResult + count;
        }
      });
    } else {
      result[file] = v;
    }
  });
}

/// Generates a merged hitmap from a set of coverage JSON files.
@Deprecated('Migrate to HitMap.parseFiles')
Future<Map<String, Map<int, int>>> parseCoverage(
  Iterable<File> files,
  int _, {
  bool checkIgnoredLines = false,
  @Deprecated('Use packagePath') String? packagesPath,
  String? packagePath,
}) async {
  final result = await HitMap.parseFiles(
    files,
    checkIgnoredLines: checkIgnoredLines,
    packagesPath: packagesPath,
    packagePath: packagePath,
  );
  return result.map((key, value) => MapEntry(key, value.lineHits));
}

/// Returns a JSON hit map backward-compatible with pre-1.16.0 SDKs.
@Deprecated('Will be removed in 2.0.0')
Map<String, dynamic> toScriptCoverageJson(Uri scriptUri, Map<int, int> hitMap) {
  return hitmapToJson(HitMap(hitMap), scriptUri);
}

List<T> _flattenMap<T>(Map map) {
  final kvs = <T>[];
  map.forEach((k, v) {
    kvs.add(k as T);
    kvs.add(v as T);
  });
  return kvs;
}

/// Returns a JSON hit map backward-compatible with pre-1.16.0 SDKs.
Map<String, dynamic> hitmapToJson(
  HitMap hitmap,
  Uri scriptUri,
) => <String, dynamic>{
  'source': '$scriptUri',
  'script': {
    'type': '@Script',
    'fixedId': true,
    'id': 'libraries/1/scripts/${Uri.encodeComponent(scriptUri.toString())}',
    'uri': '$scriptUri',
    '_kind': 'library',
  },
  'hits': _flattenMap<int>(hitmap.lineHits),
  if (hitmap.funcHits != null) 'funcHits': _flattenMap<int>(hitmap.funcHits!),
  if (hitmap.funcNames != null)
    'funcNames': _flattenMap<dynamic>(hitmap.funcNames!),
  if (hitmap.branchHits != null)
    'branchHits': _flattenMap<int>(hitmap.branchHits!),
};

/// Sorts the hits array based on the line numbers.
List _sortHits(List hits) {
  final structuredHits = <_HitInfo>[];
  for (var i = 0; i < hits.length - 1; i += 2) {
    final lineOrLineRange = hits[i];
    final firstLineInRange = lineOrLineRange is int
        ? lineOrLineRange
        : int.parse((lineOrLineRange as String).split('-')[0]);
    structuredHits.add(_HitInfo(firstLineInRange, hits[i], hits[i + 1] as int));
  }
  structuredHits.sort((a, b) => a.firstLine.compareTo(b.firstLine));
  return structuredHits
      .map((item) => [item.hitRange, item.hitCount])
      .expand((item) => item)
      .toList();
}
