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