// Copyright (c) 2019, 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 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:collection/collection.dart';
import 'package:crypto/crypto.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:nnbd_migration/src/front_end/offset_mapper.dart';
import 'package:nnbd_migration/src/front_end/unit_link.dart';
import 'package:nnbd_migration/src/front_end/web/navigation_tree.dart';
import 'package:nnbd_migration/src/hint_action.dart';
import 'package:nnbd_migration/src/preview/preview_site.dart';
import 'package:path/path.dart' as path;

/// A description of an edit that can be applied before rerunning the migration
/// in order to improve the migration results.
class EditDetail {
  /// A description of the edit that will be performed.
  final String description;

  /// The offset of the range to be replaced.
  final int offset;

  /// The length of the range to be replaced.
  final int length;

  /// The string with which the range will be replaced.
  final String replacement;

  /// Initialize a newly created detail.
  EditDetail(this.description, this.offset, this.length, this.replacement);

  /// Initializes a detail based on a [SourceEdit] object.
  factory EditDetail.fromSourceEdit(
          String description, SourceEdit sourceEdit) =>
      EditDetail(description, sourceEdit.offset, sourceEdit.length,
          sourceEdit.replacement);
}

/// A class storing rendering information for an entire migration report.
///
/// This generally provides one [InstrumentationRenderer] (for one library)
/// with information about the rest of the libraries represented in the
/// instrumentation output.
class MigrationInfo {
  /// The information about the compilation units that are are migrated.
  final Set<UnitInfo>? units;

  /// A map from file paths to the unit infos created for those files. The units
  /// in this map is a strict superset of the [units] that were migrated.
  final Map<String?, UnitInfo> unitMap;

  /// The resource provider's path context.
  final path.Context pathContext;

  /// The filesystem root used to create relative paths for each unit.
  final String? includedRoot;

  MigrationInfo(this.units, this.unitMap, this.pathContext, this.includedRoot);

  /// The path of the Dart logo displayed in the toolbar.
  String get dartLogoPath => PreviewSite.dartLogoPath;

  /// The path to the highlight.pack.js script, relative to [unitInfo].
  String get highlightJsPath => PreviewSite.highlightJsPath;

  /// The path to the highlight.pack.js stylesheet, relative to [unitInfo].
  String get highlightStylePath => PreviewSite.highlightCssPath;

  /// The path of the Material icons font.
  String get materialIconsPath => PreviewSite.materialIconsPath;

  /// The path of the Roboto font.
  String get robotoFont => PreviewSite.robotoFontPath;

  /// The path of the Roboto Mono font.
  String get robotoMonoFont => PreviewSite.robotoMonoFontPath;

  /// Returns the absolute path of [path], as relative to [includedRoot].
  String absolutePathFromRoot(String? path) =>
      pathContext.join(includedRoot!, path);

  /// Returns the relative path of [path] from [includedRoot].
  String relativePathFromRoot(String path) =>
      pathContext.relative(path, from: includedRoot);

  /// Return the path to [unit] from [includedRoot], to be used as a display
  /// name for a library.
  String computeName(UnitInfo unit) => relativePathFromRoot(unit.path!);

  List<UnitLink> unitLinks() {
    var links = <UnitLink>[];
    for (var unit in units!) {
      var count = unit.fixRegions.length;
      links.add(UnitLink(
          unit.path,
          pathContext.split(computeName(unit)),
          count,
          unit.wasExplicitlyOptedOut,
          unit.migrationStatus,
          unit.migrationStatusCanBeChanged));
    }
    return links;
  }
}

/// A location from or to which a user might want to navigate.
abstract class NavigationRegion {
  /// The offset of the region.
  final int offset;

  /// The line number of the region.
  final int? line;

  /// The length of the region.
  final int length;

  /// Initialize a newly created link.
  NavigationRegion(int offset, this.line, this.length)
      : assert(offset >= 0),
        offset = offset < 0 ? 0 : offset;
}

/// A location from which a user might want to navigate.
class NavigationSource extends NavigationRegion {
  /// The target to which the user should be navigated.
  final NavigationTarget target;

  /// Initialize a newly created link.
  NavigationSource(int offset, int? line, int length, this.target)
      : super(offset, line, length);
}

/// A location to which a user might want to navigate.
class NavigationTarget extends NavigationRegion {
  /// The file containing the anchor.
  final String filePath;

  /// Initialize a newly created anchor.
  NavigationTarget(this.filePath, int offset, int? line, int length)
      : super(offset, line, length);

  @override
  int get hashCode => JenkinsSmiHash.hash3(filePath.hashCode, offset, length);

  @override
  bool operator ==(Object other) {
    return other is NavigationTarget &&
        other.filePath == filePath &&
        other.offset == offset &&
        other.length == length;
  }

  @override
  String toString() => 'NavigationTarget["$filePath", $line, $offset, $length]';
}

/// A description of an explanation associated with a region of code that was
/// modified.
class RegionInfo {
  /// Type type of region.
  final RegionType regionType;

  /// The offset to the beginning of the region.
  final int offset;

  /// The length of the region.
  final int length;

  /// The line number of the beginning of the region.
  final int lineNumber;

  /// The explanation to be displayed for the region.
  ///
  /// `null` if this region doesn't represent a fix (e.g. it's just whitespace
  /// change to preserve formatting).
  final String? explanation;

  /// The kind of fix that was applied.
  ///
  /// `null` if this region doesn't represent a fix (e.g. it's just whitespace
  /// change to preserve formatting).
  final NullabilityFixKind? kind;

  /// Indicates whether this region should be counted in the edit summary.
  final bool isCounted;

  /// A list of the edits that are related to this range.
  List<EditDetail> edits;

  /// A list of the nullability propagation traces that are related to this
  /// range.
  List<TraceInfo> traces;

  /// Initialize a newly created region.
  RegionInfo(this.regionType, this.offset, this.length, this.lineNumber,
      this.explanation, this.kind, this.isCounted,
      {this.edits = const [], this.traces = const []});
}

/// Different types of regions that are called out.
enum RegionType {
  /// This is a region of code that was added in migration.
  add,

  /// This is a region of code that was removed in migration.
  remove,

  /// This is a region of code that wasn't changed by migration, but is being
  /// shown to give the user more information about the migration.
  informative,
}

/// Information about a single entry in a nullability trace.
class TraceEntryInfo {
  /// Text description of the entry.
  final String description;

  /// Name of the enclosing function, or `null` if not known.
  String? function;

  /// Source code location associated with the entry, or `null` if no source
  /// code location is known.
  final NavigationTarget? target;

  /// The hint actions available on this trace entry, or `[]` if none.
  final List<HintAction> hintActions;

  TraceEntryInfo(this.description, this.function, this.target,
      {this.hintActions = const []});
}

/// Information about a nullability trace.
class TraceInfo {
  /// Text description of the trace.
  final String description;

  /// List of trace entries.
  final List<TraceEntryInfo> entries;

  TraceInfo(this.description, this.entries);
}

/// The migration information associated with a single compilation unit.
class UnitInfo {
  /// The absolute and normalized path of the unit.
  final String? path;

  /// Hash of the original contents of the unit.
  List<int>? _diskContentHash;

  /// The preview content of unit.
  String? content;

  /// The information about the regions that have an explanation associated with
  /// them. The offsets in these regions are offsets into the post-edit content.
  final List<RegionInfo> regions = [];

  /// The navigation sources that are located in this file. The offsets in these
  /// sources are offsets into the pre-edit content.
  List<NavigationSource>? sources;

  /// The navigation targets that are located in this file. The offsets in these
  /// targets are offsets into the pre-edit content.
  final Set<NavigationTarget> targets = {};

  /// An offset mapper reflecting changes made by the migration edits.
  OffsetMapper migrationOffsetMapper = OffsetMapper.identity;

  /// An offset mapper reflecting changes made to disk since the migration was
  /// run, which can be rebased on [migrationOffsetMapper] to create and
  /// maintain an offset mapper from current disk state to migration result.
  OffsetMapper diskChangesOffsetMapper = OffsetMapper.identity;

  /// Whether this compilation unit was explicitly opted out of null safety at
  /// the start of this migration.
  late bool wasExplicitlyOptedOut;

  late bool migrationStatusCanBeChanged;

  /// Indicates the migration status of this unit.
  ///
  /// After all migration phases have completed, this indicates that a file was
  /// already migrated, or is being migrated during this migration.
  ///
  /// A user can change this migration status from the preview interface:
  /// * An already migrated unit cannot be changed.
  /// * During an initial migration, in which a package is migrated to null
  ///   safety, the user can toggle a file's migration status between
  ///   "migrating" and "opting out."
  /// * During a follow-up migration, in which a package has been migrated to
  ///   null safety, but some files have been opted out, the user can toggle a
  ///   file's migration status between "migrating" and "keeping opted out."
  UnitMigrationStatus? migrationStatus;

  /// Initialize a newly created unit.
  UnitInfo(this.path);

  /// Set the original/disk content of this file to later use [hadDiskContent].
  /// This does not have a getter because it is backed by a private hash.
  set diskContent(String? originalContent) {
    _diskContentHash = md5.convert((originalContent ?? '').codeUnits).bytes;
  }

  /// Returns the [regions] that represent a fixed (changed) region of code.
  List<RegionInfo> get fixRegions => regions
      .where((region) =>
          region.regionType != RegionType.informative && region.kind != null)
      .toList();

  /// Returns the [regions] that are informative.
  List<RegionInfo> get informativeRegions => regions
      .where((region) =>
          region.regionType == RegionType.informative && region.kind != null)
      .toList();

  /// The object used to map the pre-edit offsets in the navigation targets to
  /// the post-edit offsets in the [content].
  OffsetMapper get offsetMapper =>
      OffsetMapper.rebase(diskChangesOffsetMapper, migrationOffsetMapper);

  /// Check if this unit's file had expected disk contents [checkContent].
  bool hadDiskContent(String? checkContent) {
    assert(_diskContentHash != null);
    return const ListEquality().equals(
        _diskContentHash, md5.convert((checkContent ?? '').codeUnits).bytes);
  }

  void handleSourceEdit(SourceEdit sourceEdit) {
    final contentCopy = content;
    final regionsCopy = List<RegionInfo>.from(regions);
    final insertLength = sourceEdit.replacement.length;
    final deleteLength = sourceEdit.length;
    final migratedOffset = offsetMapper.map(sourceEdit.offset);
    final diskOffset = diskChangesOffsetMapper.map(sourceEdit.offset);
    if (migratedOffset == null || diskOffset == null) {
      throw StateError('cannot apply replacement, offset has been deleted.');
    }
    try {
      content = content!.replaceRange(migratedOffset,
          migratedOffset + deleteLength, sourceEdit.replacement);
      regions.clear();
      regions.addAll(regionsCopy
          .where((region) => region.offset + region.length <= migratedOffset));
      regions.addAll(regionsCopy
          .where((region) => region.offset >= migratedOffset + deleteLength)
          .map((region) => RegionInfo(
              region.regionType,
              // TODO: perhaps this should be handled by offset mapper instead,
              // since offset mapper handles navigation, edits, and traces, and
              // this is the odd ball out.
              region.offset + insertLength - deleteLength,
              region.length,
              region.lineNumber,
              region.explanation,
              region.kind,
              region.isCounted,
              edits: region.edits,
              traces: region.traces)));

      diskChangesOffsetMapper = OffsetMapper.sequence(
          diskChangesOffsetMapper,
          OffsetMapper.forReplacement(
              diskOffset, deleteLength, sourceEdit.replacement));
    } catch (e) {
      regions.clear();
      regions.addAll(regionsCopy);
      content = contentCopy;
      rethrow;
    }
  }

  /// Returns the [RegionInfo] at offset [offset].
  // TODO(srawlins): This is O(n), used each time the user clicks on a region.
  //  Consider changing the type of [regions] to facilitate O(1) searching.
  RegionInfo regionAt(int offset) => regions
      .firstWhere((region) => region.kind != null && region.offset == offset);
}
