// 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 'dart:collection';

import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart'
    show SourceFileEdit;
import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart';
import 'package:analyzer_plugin/utilities/navigation/navigation_dart.dart';
import 'package:cli_util/cli_logging.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/fix_reason_target.dart';
import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:nnbd_migration/src/edit_plan.dart';
import 'package:nnbd_migration/src/front_end/dartfix_listener.dart';
import 'package:nnbd_migration/src/front_end/driver_provider_impl.dart';
import 'package:nnbd_migration/src/front_end/instrumentation_information.dart';
import 'package:nnbd_migration/src/front_end/migration_info.dart';
import 'package:nnbd_migration/src/front_end/offset_mapper.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/utilities/progress_bar.dart';

/// A builder used to build the migration information for a library.
class InfoBuilder {
  /// The node mapper for the migration state.
  NodeMapper? nodeMapper;

  /// The logger to use for showing progress when explaining the migration.
  final Logger _logger;

  /// The resource provider used to access the file system.
  ResourceProvider provider;

  String? includedPath;

  /// The instrumentation information gathered while the migration engine was
  /// running.
  final InstrumentationInformation info;

  /// The listener used to gather the changes to be applied.
  final DartFixListener? listener;

  /// The [NullabilityMigration] instance for this migration.
  final NullabilityMigration? migration;

  /// A map from the path of a compilation unit to the information about that
  /// unit.
  final Map<String?, UnitInfo> unitMap = {};

  /// A function which returns whether a file at a given path should be
  /// migrated.
  final bool Function(String?) shouldBeMigratedFunction;

  /// The set of files which are being considered for migration.
  final Iterable<String?>? _pathsToProcess;

  /// Initialize a newly created builder.
  InfoBuilder(
      this.provider,
      this.includedPath,
      this.info,
      this.listener,
      this.migration,
      this.nodeMapper,
      this._logger,
      this.shouldBeMigratedFunction,
      this._pathsToProcess);

  /// The provider used to get information about libraries.
  DriverProviderImpl? get driverProvider => listener!.server;

  /// Return the migration information for all of the libraries that were
  /// migrated.
  Future<Set<UnitInfo>> explainMigration() async {
    var sourceInfoMap = info.sourceInformation;
    Set<UnitInfo> units =
        SplayTreeSet<UnitInfo>((u1, u2) => u1.path!.compareTo(u2.path!));

    // Collect all of the sources for which we have [SourceInformation], as well
    // as all files which are being "processed" during this migration, which may
    // include already migrated files.
    var sources = {
      ...sourceInfoMap.keys.map((source) => source!.fullName),
      ..._pathsToProcess!,
    };
    var progressBar = ProgressBar(_logger, sources.length);

    for (var filePath in sources) {
      progressBar.tick();
      var session = driverProvider!.getAnalysisSession(filePath);
      var result = await session.getResolvedLibrary2(filePath!);
      if (result is ResolvedLibraryResult) {
        for (var unitResult in result.units!) {
          var sourceInfo =
              sourceInfoMap[unitResult.unit!.declaredElement!.source];
          // Note: there might have been no information for this unit in
          // sourceInfoMap.  That can happen if there's an already-migrated
          // library being referenced by the code being migrated, but not all
          // parts of that library are referenced.  To avoid exceptions later
          // on, we just create an empty SourceInformation object.
          // TODO(paulberry): we don't do a good job of the case where the
          // already-migrated library's defining compilation unit isn't
          // referenced (we'll just skip the entire library because we'll only
          // ever see its parts).
          sourceInfo ??= SourceInformation();
          var edit = listener!.sourceChange.getFileEdit(unitResult.path);
          var unit = _explainUnit(sourceInfo, unitResult, edit);
          if (_pathsToProcess!.contains(unitResult.path)) {
            units.add(unit);
          }
        }
      }
    }
    progressBar.complete();
    return units;
  }

  Iterable<EdgeInfo> upstreamTriggeredEdges(NullabilityNodeInfo node,
      {bool skipExactNullable = true}) {
    var edges = <EdgeInfo>[];
    for (var edge in node.upstreamEdges) {
      if (skipExactNullable &&
          node.isExactNullable &&
          edge.sourceNode!.isExactNullable) {
        // When an exact nullable points here, the nullability propagated
        // in the other direction.
        continue;
      }
      if (edge.isTriggered) {
        edges.add(edge);
      }
    }
    for (final containerNode in node.outerCompoundNodes) {
      // We must include the exact nullable edges in the upstream triggered
      // edges of the container node. If this node is in a substitution node,
      // then it's possible it was marked exact nullable because it's container
      // was marked nullable. It's container could have been marked nullable by
      // another exact nullable node. We cannot tell. Err on the side of
      // surfacing too many reasons.
      edges.addAll(
          upstreamTriggeredEdges(containerNode, skipExactNullable: false));
    }

    return edges;
  }

  void _addSimpleTrace(SimpleFixReasonInfo info, List<TraceInfo> traces) {
    traces.add(TraceInfo(
        'Reason', [_makeTraceEntry(info.description, info.codeReference)]));
  }

  /// Returns a list of edits that can be applied.
  List<EditDetail> _computeEdits(
      AtomicEditInfo fixInfo, int offset, ResolvedUnitResult result) {
    var content = result.content;

    EditDetail removeHint(String description) => EditDetail.fromSourceEdit(
        description,
        fixInfo.hintComment!.changesToRemove(content).toSourceEdits().single);

    EditDetail changeHint(String description, String replacement) =>
        EditDetail.fromSourceEdit(
            description,
            fixInfo.hintComment!
                .changesToReplace(content, replacement)
                .toSourceEdits()
                .single);

    var edits = <EditDetail>[];
    var fixKind = fixInfo.description.kind;
    switch (fixKind) {
      case NullabilityFixKind.addLateDueToHint:
        edits.add(removeHint('Remove /*late*/ hint'));
        break;
      case NullabilityFixKind.addLateFinalDueToHint:
        edits.add(removeHint('Remove /*late final*/ hint'));
        break;
      case NullabilityFixKind.addRequired:
        var metaImport =
            _findImportDirective(result.unit!, 'package:meta/meta.dart');
        if (metaImport == null) {
          edits.add(
              EditDetail('Add /*required*/ hint', offset, 0, '/*required*/ '));
        } else {
          var prefix = metaImport.prefix?.name;
          if (prefix == null) {
            edits.add(
                EditDetail("Mark with '@required'", offset, 0, '@required '));
          } else {
            edits.add(EditDetail(
                "Mark with '@required'", offset, 0, '@$prefix.required '));
          }
        }
        break;
      case NullabilityFixKind.checkExpression:
        // TODO(brianwilkerson) Determine whether we can know that the fix is
        //  associated with a parameter and insert an assert if it is.
        edits.add(EditDetail('Add /*!*/ hint', offset, 0, '/*!*/'));
        break;
      case NullabilityFixKind.checkExpressionDueToHint:
        edits.add(removeHint('Remove /*!*/ hint'));
        break;
      case NullabilityFixKind.downcastExpression:
      case NullabilityFixKind.otherCastExpression:
        // There's no useful hint to apply to casts.
        break;
      case NullabilityFixKind.removeAs:
      case NullabilityFixKind.removeDeadCode:
      case NullabilityFixKind.removeLanguageVersionComment:
        // There's no need for hints around code that is being removed.
        break;
      case NullabilityFixKind.addType:
      case NullabilityFixKind.replaceVar:
        // There's no need for hints around inserted types.
        break;
      case NullabilityFixKind.makeTypeNullable:
      case NullabilityFixKind.typeNotMadeNullable:
        edits.add(EditDetail('Add /*!*/ hint', offset, 0, '/*!*/'));
        edits.add(EditDetail('Add /*?*/ hint', offset, 0, '/*?*/'));
        break;
      case NullabilityFixKind.makeTypeNullableDueToHint:
        edits.add(changeHint('Change to /*!*/ hint', '/*!*/'));
        edits.add(removeHint('Remove /*?*/ hint'));
        break;
      case NullabilityFixKind.typeNotMadeNullableDueToHint:
        edits.add(removeHint('Remove /*!*/ hint'));
        edits.add(changeHint('Change to /*?*/ hint', '/*?*/'));
        break;
      case NullabilityFixKind.addLate:
      case NullabilityFixKind.addLateDueToTestSetup:
        // We could add an edit to add a `/*?*/` hint, but the offset is a
        // little tricky.
        break;
      case NullabilityFixKind.conditionFalseInStrongMode:
      case NullabilityFixKind.conditionTrueInStrongMode:
      case NullabilityFixKind.nullAwarenessUnnecessaryInStrongMode:
      case NullabilityFixKind.nullAwareAssignmentUnnecessaryInStrongMode:
        // We don't offer any edits around weak-only code.
        // TODO(paulberry): offer edits to delete the code that would be dead in
        // strong mode (https://github.com/dart-lang/sdk/issues/41554).
        break;
      case NullabilityFixKind.compoundAssignmentHasBadCombinedType:
      case NullabilityFixKind.compoundAssignmentHasNullableSource:
        // We don't offer any edits around bad compound assignments or bad
        // increment/decrement operations.
        break;
      case NullabilityFixKind.addImport:
      case NullabilityFixKind.changeMethodName:
        // These fix kinds have to do with changing iterable method calls to
        // their "OrNull" equivalents.  We don't offer any hints around
        // this transformation.
        break;
      case NullabilityFixKind.noValidMigrationForNull:
        // We don't offer any edits around unmigratable `null`s.  The user has
        // to fix manually.
        break;
      case NullabilityFixKind.addThen:
        // We don't offer any edits around addition of `.then` to a future.
        break;
    }
    return edits;
  }

  /// Return the navigation sources for the unit associated with the [result].
  List<NavigationSource> _computeNavigationSources(ResolvedUnitResult result) {
    var collector = NavigationCollectorImpl();
    computeDartNavigation(
        result.session.resourceProvider, collector, result.unit!, null, null);
    collector.createRegions();
    var files = collector.files;
    var regions = collector.regions;
    var rawTargets = collector.targets;
    var convertedTargets =
        List<NavigationTarget?>.filled(rawTargets.length, null);
    return regions.map((region) {
      var targets = region.targets;
      if (targets.isEmpty) {
        throw StateError('Targets is empty');
      }
      var target = convertedTargets[targets[0]];
      if (target == null) {
        var rawTarget = rawTargets[targets[0]];
        target = _targetForRawTarget(files[rawTarget.fileIndex], rawTarget);
        convertedTargets[targets[0]] = target;
      }
      return NavigationSource(
          region.offset, null /* line */, region.length, target);
    }).toList();
  }

  void _computeTraceNonNullableInfo(NullabilityNodeInfo node,
      List<TraceInfo> traces, FixReasonTarget target) {
    var entries = <TraceEntryInfo>[];
    var description = 'Non-nullability reason${target.suffix}';
    var step = node.whyNotNullable;
    if (step == null) {
      if (node != info.never) {
        // 'never' indicates we're describing an edge to never, such as a `!`.
        traces.add(TraceInfo(description, [
          _nodeToTraceEntry(node,
              description: 'No reason found to make nullable')
        ]));
      }
      return;
    }
    assert(identical(step.node, node));
    while (step != null && !step.isStartingPoint) {
      entries.add(_nodeToTraceEntry(step.node));
      if (step.codeReference != null) {
        entries.add(_stepToTraceEntry(step));
      }
      step = step.principalCause;
    }
    traces.add(TraceInfo(description, entries));
  }

  void _computeTraceNullableInfo(NullabilityNodeInfo node,
      List<TraceInfo> traces, FixReasonTarget target) {
    var entries = <TraceEntryInfo>[];
    var step = node.whyNullable;
    if (step == null) {
      return;
    }
    assert(identical(step.targetNode, node));
    while (step != null) {
      entries.add(_nodeToTraceEntry(step.targetNode!));
      if (step.codeReference != null) {
        entries.add(_stepToTraceEntry(step));
      }
      step = step.principalCause;
    }
    var description = 'Nullability reason${target.suffix}';
    traces.add(TraceInfo(description, entries));
  }

  List<TraceInfo> _computeTraces(
      Map<FixReasonTarget?, FixReasonInfo?> fixReasons) {
    var traces = <TraceInfo>[];
    for (var entry in fixReasons.entries) {
      var reason = entry.value;
      if (reason is NullabilityNodeInfo) {
        if (reason.isNullable) {
          _computeTraceNullableInfo(reason, traces, FixReasonTarget.root);
        } else {
          _computeTraceNonNullableInfo(reason, traces, FixReasonTarget.root);
        }
      } else if (reason is EdgeInfo) {
        if (reason.sourceNode!.isNullable &&
            !reason.destinationNode.isNullable) {
          var target = entry.key!;
          _computeTraceNullableInfo(reason.sourceNode!, traces, target);
          _computeTraceNonNullableInfo(reason.destinationNode, traces, target);
        }
      } else if (reason is SimpleFixReasonInfo) {
        _addSimpleTrace(reason, traces);
      } else {
        assert(false, 'Unrecognized reason type: ${reason.runtimeType}');
      }
    }
    return traces;
  }

  /// Return the migration information for the unit associated with the
  /// [result].
  UnitInfo _explainUnit(SourceInformation sourceInfo, ResolvedUnitResult result,
      SourceFileEdit? fileEdit) {
    var unitInfo = _unitForPath(result.path);
    unitInfo.sources ??= _computeNavigationSources(result);
    var content = result.content;
    unitInfo.diskContent = content;
    var alreadyMigrated =
        result.unit!.featureSet.isEnabled(Feature.non_nullable);
    unitInfo.wasExplicitlyOptedOut = result.unit!.languageVersionToken != null;
    if (alreadyMigrated) {
      unitInfo.migrationStatus = UnitMigrationStatus.alreadyMigrated;
      unitInfo.migrationStatusCanBeChanged = false;
    } else if (shouldBeMigratedFunction(result.path)) {
      unitInfo.migrationStatus = UnitMigrationStatus.migrating;
      unitInfo.migrationStatusCanBeChanged = true;
    } else {
      unitInfo.migrationStatus = UnitMigrationStatus.optingOut;
      unitInfo.migrationStatusCanBeChanged = false;
    }
    var regions = unitInfo.regions;

    // There are certain rare conditions involving generated code in a bazel
    // workspace that can cause a source file to get processed more than once by
    // the migration tool (sometimes with a correct URI, sometimes with an
    // incorrect URI that corresponds to a file path in the `bazel-out`
    // directory).  That can cause this method to get called twice for the same
    // unit.  To avoid this creating user-visible problems, we need to ensure
    // that any regions left over from the previous invocation are cleared out
    // before we re-populate the region list.
    regions.clear();

    var lineInfo = result.unit!.lineInfo;
    var insertions = <int?, List<AtomicEdit>>{};
    var infosSeen = Set<AtomicEditInfo>.identity();

    // Apply edits and build the regions.
    var changes = sourceInfo.changes ?? {};
    var sourceOffsets = changes.keys.toList();
    sourceOffsets.sort();
    var offset = 0;
    var sourceOffset = 0;
    for (var nextSourceOffset in sourceOffsets) {
      var changesForSourceOffset = changes[nextSourceOffset]!;
      var unchangedTextLength = nextSourceOffset! - sourceOffset;
      offset += unchangedTextLength;
      sourceOffset += unchangedTextLength;
      for (var edit in changesForSourceOffset) {
        var length = edit.length;
        var replacement = edit.replacement;
        var end = offset + length;
        // Insert the replacement text without deleting the replaced text.
        if (replacement.isNotEmpty) {
          content = content!.replaceRange(end, end, replacement);
          (insertions[sourceOffset] ??= []).add(AtomicEdit.insert(replacement));
        }
        var info = edit.info;
        var edits = info != null
            ? _computeEdits(info, sourceOffset, result)
            : <EditDetail>[];
        var lineNumber = lineInfo!.getLocation(sourceOffset).lineNumber;
        var traces = info == null
            ? const <TraceInfo>[]
            : _computeTraces(info.fixReasons);
        var description = info?.description;
        var isCounted = info != null && infosSeen.add(info);
        var explanation = description?.appliedMessage;
        var kind = description?.kind;
        if (edit.isInsertion) {
          regions.add(RegionInfo(
              edit.isInformative ? RegionType.informative : RegionType.add,
              offset,
              replacement.length,
              lineNumber,
              explanation,
              kind,
              isCounted,
              edits: edits,
              traces: traces));
        } else if (edit.isDeletion) {
          regions.add(RegionInfo(
              edit.isInformative ? RegionType.informative : RegionType.remove,
              offset,
              length,
              lineNumber,
              explanation,
              kind,
              isCounted,
              edits: edits,
              traces: traces));
        } else if (edit.isReplacement) {
          assert(!edit.isInformative);
          regions.add(RegionInfo(RegionType.remove, offset, length, lineNumber,
              explanation, kind, isCounted,
              edits: edits, traces: traces));
          regions.add(RegionInfo(RegionType.add, end, replacement.length,
              lineNumber, explanation, kind, isCounted,
              edits: edits, traces: traces));
        } else {
          throw StateError(
              'Edit is not an insertion, deletion, replacement, nor '
              'informative: $edit');
        }
        sourceOffset += length;
        offset += length + replacement.length;
      }
    }

    // Build the map from source file offset to offset in the modified text.
    // We only account for insertions because in the code above, we don't delete
    // the modified text.
    var edits = insertions.toSourceEdits();
    edits.sort((first, second) => first.offset.compareTo(second.offset));
    var mapper = OffsetMapper.forEdits(edits);
    regions.sort((first, second) => first.offset.compareTo(second.offset));
    unitInfo.migrationOffsetMapper = mapper;
    unitInfo.content = content;
    return unitInfo;
  }

  /// Searches [unit] for an import directive whose URI matches [uri], returning
  /// it if found, or `null` if not found.
  ImportDirective? _findImportDirective(CompilationUnit unit, String uri) {
    for (var directive in unit.directives) {
      if (directive is ImportDirective && directive.uriContent == uri) {
        return directive;
      }
    }
    return null;
  }

  TraceEntryInfo _makeTraceEntry(
      String description, CodeReference? codeReference,
      {List<HintAction> hintActions = const []}) {
    var length = 1; // TODO(paulberry): figure out the correct value.
    return TraceEntryInfo(
        description,
        codeReference?.function,
        codeReference == null
            ? null
            : NavigationTarget(codeReference.path, codeReference.offset,
                codeReference.line, length),
        hintActions: hintActions);
  }

  TraceEntryInfo _nodeToTraceEntry(NullabilityNodeInfo node,
      {String? description}) {
    description ??= node.toString(); // TODO(paulberry): improve this message
    return _makeTraceEntry(description, node.codeReference,
        hintActions: node.hintActions.keys
            .map((kind) => HintAction(kind, nodeMapper!.idForNode(node)))
            .toList());
  }

  TraceEntryInfo _stepToTraceEntry(PropagationStepInfo step) {
    var description = step.edge?.description;
    description ??= step.toString(); // TODO(paulberry): improve this message.
    return _makeTraceEntry(description, step.codeReference);
  }

  /// Return the navigation target in the file with the given [filePath] at the
  /// given [offset] ans with the given [length].
  NavigationTarget _targetForRawTarget(
      String filePath, protocol.NavigationTarget rawTarget) {
    var unitInfo = _unitForPath(filePath);
    var offset = rawTarget.offset;
    var length = rawTarget.length;
    var target = NavigationTarget(filePath, offset, null /* line */, length);
    unitInfo.targets.add(target);
    return target;
  }

  /// Return the unit info for the file at the given [path].
  UnitInfo _unitForPath(String? path) {
    return unitMap.putIfAbsent(path, () => UnitInfo(path));
  }

  /// Builds a description for [node]'s enclosing member(s).
  ///
  /// This may include a class and method name, for example, or the name of the
  /// enclosing top-level member.
  @visibleForTesting
  static String buildEnclosingMemberDescription(AstNode? node) {
    for (var enclosingNode = node;
        enclosingNode != null;
        enclosingNode = enclosingNode.parent) {
      if (enclosingNode is ConstructorDeclaration) {
        if (enclosingNode.name == null) {
          return _describeClassOrExtensionMember(
              enclosingNode.parent as CompilationUnitMember?,
              'the default constructor of',
              '');
        } else {
          return _describeClassOrExtensionMember(
              enclosingNode.parent as CompilationUnitMember?,
              'the constructor',
              enclosingNode.name!.name);
        }
      } else if (enclosingNode is MethodDeclaration) {
        var functionName = enclosingNode.name.name;
        String baseDescription;
        if (enclosingNode.isGetter) {
          baseDescription = 'the getter';
        } else if (enclosingNode.isOperator) {
          baseDescription = 'the operator';
        } else if (enclosingNode.isSetter) {
          baseDescription = 'the setter';
          functionName += '=';
        } else {
          baseDescription = 'the method';
        }
        return _describeClassOrExtensionMember(
            enclosingNode.parent as CompilationUnitMember?,
            baseDescription,
            functionName);
      } else if (enclosingNode is FunctionDeclaration &&
          enclosingNode.parent is CompilationUnit) {
        var functionName = enclosingNode.name.name;
        String baseDescription;
        if (enclosingNode.isGetter) {
          baseDescription = 'the getter';
        } else if (enclosingNode.isSetter) {
          baseDescription = 'the setter';
          functionName += '=';
        } else {
          baseDescription = 'the function';
        }
        return "$baseDescription '$functionName'";
      } else if (enclosingNode is VariableDeclaration) {
        var description = _describeVariableDeclaration(enclosingNode);
        if (description != null) return description;
      } else if (enclosingNode is VariableDeclarationList) {
        var description =
            _describeVariableDeclaration(enclosingNode.variables[0]);
        if (description != null) return description;
      }
    }
    throw ArgumentError(
        "Can't describe enclosing member of ${node.runtimeType}");
  }

  static String _describeClassOrExtensionMember(CompilationUnitMember? parent,
      String baseDescription, String functionName) {
    if (parent is NamedCompilationUnitMember) {
      var parentName = parent.name.name;
      if (functionName.isEmpty) {
        return "$baseDescription '$parentName'";
      } else {
        return "$baseDescription '$parentName.$functionName'";
      }
    } else if (parent is ExtensionDeclaration) {
      if (parent.name == null) {
        var extendedTypeString = parent.extendedType.type!.getDisplayString(
          withNullability: false,
        );
        return "$baseDescription '$functionName' in unnamed extension on $extendedTypeString";
      } else {
        return "$baseDescription '${parent.name!.name}.$functionName'";
      }
    } else {
      throw ArgumentError(
          'Unexpected class or extension type ${parent.runtimeType}');
    }
  }

  static String? _describeVariableDeclaration(VariableDeclaration node) {
    var variableName = node.name.name;
    var parent = node.parent!;
    var grandParent = parent.parent;
    if (grandParent is FieldDeclaration) {
      return _describeClassOrExtensionMember(
          grandParent.parent as CompilationUnitMember?,
          'the field',
          variableName);
    } else if (grandParent is TopLevelVariableDeclaration) {
      return "the variable '$variableName'";
    } else {
      return null;
    }
  }
}
