// 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/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:nnbd_migration/src/decorated_class_hierarchy.dart';
import 'package:nnbd_migration/src/decorated_type.dart';
import 'package:nnbd_migration/src/edge_builder.dart';
import 'package:nnbd_migration/src/edit_plan.dart';
import 'package:nnbd_migration/src/exceptions.dart';
import 'package:nnbd_migration/src/fix_aggregator.dart';
import 'package:nnbd_migration/src/fix_builder.dart';
import 'package:nnbd_migration/src/node_builder.dart';
import 'package:nnbd_migration/src/nullability_node.dart';
import 'package:nnbd_migration/src/postmortem_file.dart';
import 'package:nnbd_migration/src/variables.dart';

/// Implementation of the [NullabilityMigration] public API.
class NullabilityMigrationImpl implements NullabilityMigration {
  /// Set this constant to a pathname to cause nullability migration to output
  /// a post-mortem file that can be later examined by tool/postmortem.dart.
  static const String _postmortemPath = null;

  final NullabilityMigrationListener listener;

  Variables _variables;

  final NullabilityGraph _graph;

  final bool _permissive;

  final NullabilityMigrationInstrumentation _instrumentation;

  DecoratedClassHierarchy _decoratedClassHierarchy;

  bool _propagated = false;

  /// Indicates whether code removed by the migration engine should be removed
  /// by commenting it out.  A value of `false` means to actually delete the
  /// code that is removed.
  final bool removeViaComments;

  final bool warnOnWeakCode;

  final _decoratedTypeParameterBounds = DecoratedTypeParameterBounds();

  /// If not `null`, the object that will be used to write out post-mortem
  /// information once migration is complete.
  final PostmortemFileWriter _postmortemFileWriter =
      _makePostmortemFileWriter();

  final LineInfo Function(String) _getLineInfo;

  /// Indicates whether we should transform iterable methods taking an "orElse"
  /// parameter into their "OrNull" equivalents if possible.
  final bool transformWhereOrNull;

  /// Map from [Source] object to a boolean indicating whether the source is
  /// opted in to null safety.
  final Map<Source, bool> _libraryOptInStatus = {};

  /// Indicates whether the client has used the [unmigratedDependencies] getter.
  bool _queriedUnmigratedDependencies = false;

  /// Prepares to perform nullability migration.
  ///
  /// If [permissive] is `true`, exception handling logic will try to proceed
  /// as far as possible even though the migration algorithm is not yet
  /// complete.  TODO(paulberry): remove this mode once the migration algorithm
  /// is fully implemented.
  ///
  /// Optional parameter [removeViaComments] indicates whether code that the
  /// migration tool wishes to remove should instead be commenting it out.
  ///
  /// Optional parameter [warnOnWeakCode] indicates whether weak-only code
  /// should be warned about or removed (in the way specified by
  /// [removeViaComments]).
  ///
  /// Optional parameter [transformWhereOrNull] indicates whether Iterable
  /// methods should be transformed to their "OrNull" equivalents when possible.
  /// This feature is a work in progress, so by default they are not
  /// transformed.
  NullabilityMigrationImpl(NullabilityMigrationListener listener,
      LineInfo Function(String) getLineInfo,
      {bool permissive = false,
      NullabilityMigrationInstrumentation instrumentation,
      bool removeViaComments = false,
      bool warnOnWeakCode = true,
      bool transformWhereOrNull = true})
      : this._(
            listener,
            NullabilityGraph(instrumentation: instrumentation),
            permissive,
            instrumentation,
            removeViaComments,
            warnOnWeakCode,
            getLineInfo,
            transformWhereOrNull);

  NullabilityMigrationImpl._(
      this.listener,
      this._graph,
      this._permissive,
      this._instrumentation,
      this.removeViaComments,
      this.warnOnWeakCode,
      this._getLineInfo,
      this.transformWhereOrNull) {
    _instrumentation?.immutableNodes(_graph.never, _graph.always);
    _postmortemFileWriter?.graph = _graph;
  }

  @override
  bool get isPermissive => _permissive;

  @override
  List<String> get unmigratedDependencies {
    _queriedUnmigratedDependencies = true;
    var unmigratedDependencies = <Source>[];
    for (var entry in _libraryOptInStatus.entries) {
      if (_graph.isBeingMigrated(entry.key)) continue;
      if (!entry.value) {
        unmigratedDependencies.add(entry.key);
      }
    }
    var badUris = {
      for (var dependency in unmigratedDependencies) dependency.uri.toString()
    }.toList();
    badUris.sort();
    return badUris;
  }

  @override
  void finalizeInput(ResolvedUnitResult result) {
    if (result.unit.featureSet.isEnabled(Feature.non_nullable)) {
      // This library has already been migrated; nothing more to do.
      return;
    }
    ExperimentStatusException.sanityCheck(result);
    if (!_propagated) {
      _propagated = true;
      _graph.propagate(_postmortemFileWriter);
    }
    var unit = result.unit;
    var compilationUnit = unit.declaredElement;
    var library = compilationUnit.library;
    var source = compilationUnit.source;
    // Hierarchies were created assuming the libraries being migrated are opted
    // out, but the FixBuilder will analyze assuming they're opted in.  So we
    // need to clear the hierarchies before we continue.
    (result.session as AnalysisSessionImpl).clearHierarchies();
    var fixBuilder = FixBuilder(
        source,
        _decoratedClassHierarchy,
        result.typeProvider,
        library.typeSystem as TypeSystemImpl,
        _variables,
        library,
        _permissive ? listener : null,
        unit,
        warnOnWeakCode,
        _graph,
        transformWhereOrNull);
    try {
      DecoratedTypeParameterBounds.current = _decoratedTypeParameterBounds;
      fixBuilder.visitAll();
    } finally {
      DecoratedTypeParameterBounds.current = null;
    }
    var changes = FixAggregator.run(unit, result.content, fixBuilder.changes,
        removeViaComments: removeViaComments, warnOnWeakCode: warnOnWeakCode);
    _instrumentation?.changes(source, changes);
    final lineInfo = LineInfo.fromContent(source.contents.data);
    var offsets = changes.keys.toList();
    offsets.sort();
    for (var offset in offsets) {
      var edits = changes[offset];
      var descriptions = edits
          .map((edit) => edit.info)
          .where((info) => info != null)
          .map((info) => info.description.appliedMessage)
          .join(', ');
      var sourceEdit = edits.toSourceEdit(offset);
      listener.addSuggestion(
          descriptions, _computeLocation(lineInfo, sourceEdit, source));
      listener.addEdit(source, sourceEdit);
    }
  }

  void finish() {
    if (!_propagated) {
      // [finalizeInput] sets this field to `true`, so if it's still false, that
      // means it was never called; this probably means that all the code fed
      // to the migration tool was already migrated.
      throw ExperimentStatusException.migratedAlready();
    }
    _postmortemFileWriter?.write();
    _instrumentation?.finished();
  }

  void prepareInput(ResolvedUnitResult result) {
    assert(
        !_queriedUnmigratedDependencies,
        'Should only query unmigratedDependencies after all calls to '
        'prepareInput');
    if (result.unit.featureSet.isEnabled(Feature.non_nullable)) {
      // This library has already been migrated; nothing more to do.
      return;
    }
    ExperimentStatusException.sanityCheck(result);
    _recordTransitiveImportExportOptInStatus(
        result.libraryElement.importedLibraries);
    _recordTransitiveImportExportOptInStatus(
        result.libraryElement.exportedLibraries);
    if (_variables == null) {
      _variables = Variables(_graph, result.typeProvider, _getLineInfo,
          instrumentation: _instrumentation,
          postmortemFileWriter: _postmortemFileWriter);
      _decoratedClassHierarchy = DecoratedClassHierarchy(_variables, _graph);
    }
    var unit = result.unit;
    try {
      DecoratedTypeParameterBounds.current = _decoratedTypeParameterBounds;
      unit.accept(NodeBuilder(
          _variables,
          unit.declaredElement.source,
          _permissive ? listener : null,
          _graph,
          result.typeProvider,
          _getLineInfo,
          instrumentation: _instrumentation));
    } finally {
      DecoratedTypeParameterBounds.current = null;
    }
  }

  void processInput(ResolvedUnitResult result) {
    if (result.unit.featureSet.isEnabled(Feature.non_nullable)) {
      // This library has already been migrated; nothing more to do.
      return;
    }
    ExperimentStatusException.sanityCheck(result);
    var unit = result.unit;
    try {
      DecoratedTypeParameterBounds.current = _decoratedTypeParameterBounds;
      unit.accept(EdgeBuilder(
          result.typeProvider,
          result.typeSystem,
          _variables,
          _graph,
          unit.declaredElement.source,
          _permissive ? listener : null,
          _decoratedClassHierarchy,
          transformWhereOrNull,
          instrumentation: _instrumentation));
    } finally {
      DecoratedTypeParameterBounds.current = null;
    }
  }

  @override
  void update() {
    _graph.update(_postmortemFileWriter);
  }

  /// Records the opt in/out status of all libraries in [libraries], and any
  /// libraries they transitively import or export, in [_libraryOptInStatus].
  void _recordTransitiveImportExportOptInStatus(
      Iterable<LibraryElement> libraries) {
    var librariesToCheck = libraries.toList();
    while (librariesToCheck.isNotEmpty) {
      var library = librariesToCheck.removeLast();
      if (_libraryOptInStatus.containsKey(library.source)) continue;
      _libraryOptInStatus[library.source] = library.isNonNullableByDefault;
      librariesToCheck.addAll(library.importedLibraries);
      librariesToCheck.addAll(library.exportedLibraries);
    }
  }

  static Location _computeLocation(
      LineInfo lineInfo, SourceEdit edit, Source source) {
    final locationInfo = lineInfo.getLocation(edit.offset);
    var location = Location(
      source.fullName,
      edit.offset,
      edit.length,
      locationInfo.lineNumber,
      locationInfo.columnNumber,
    );
    return location;
  }

  static PostmortemFileWriter _makePostmortemFileWriter() {
    if (_postmortemPath == null) return null;
    return PostmortemFileWriter(
        PhysicalResourceProvider.INSTANCE.getFile(_postmortemPath));
  }
}
