// 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,
  }) {
    final loader = Loader();

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

      var ignoredLinesList = <List<int>>[];

      if (checkIgnoredLines) {
        if (ignoredLinesInFilesCache.containsKey(source)) {
          final cacheHit = ignoredLinesInFilesCache[source];
          if (cacheHit == null) {
            // Null-entry indicates that the whole file was ignored.
            continue;
          }
          ignoredLinesList = cacheHit;
        } else {
          final path = resolver.resolve(source);
          if (path != null) {
            final lines = loader.loadSync(path) ?? [];
            ignoredLinesList = getIgnoredLines(path, lines);

            // Ignore the whole file.
            if (ignoredLinesList.length == 1 &&
                ignoredLinesList[0][0] == 0 &&
                ignoredLinesList[0][1] == lines.length) {
              // Null-entry indicates that the whole file was ignored.
              ignoredLinesInFilesCache[source] = null;
              continue;
            }
            ignoredLinesInFilesCache[source] = ignoredLinesList;
          } else {
            // Couldn't resolve source. Allow cache to answer next time
            // anyway.
            ignoredLinesInFilesCache[source] = ignoredLinesList;
          }
        }
      }

      // Move to the first ignore range.
      final ignoredLines = ignoredLinesList.iterator;
      var hasCurrent = ignoredLines.moveNext();

      bool shouldIgnoreLine(Iterator<List<int>> ignoredRanges, int line) {
        if (!hasCurrent || ignoredRanges.current.isEmpty) {
          return false;
        }

        if (line < ignoredRanges.current[0]) return false;

        while (hasCurrent &&
            ignoredRanges.current.isNotEmpty &&
            ignoredRanges.current[1] < line) {
          hasCurrent = ignoredRanges.moveNext();
        }

        if (hasCurrent &&
            ignoredRanges.current.isNotEmpty &&
            ignoredRanges.current[0] <= line &&
            line <= ignoredRanges.current[1]) {
          return true;
        }

        return false;
      }

      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.
            if (shouldIgnoreLine(ignoredLines, k)) continue;

            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++) {
              if (shouldIgnoreLine(ignoredLines, j)) continue;

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

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