// 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';
import 'package:pub_semver/pub_semver.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;

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

  /// Map of additional package dependencies that will be required by the
  /// migrated code.  Keys are package names; values indicate the minimum
  /// required version of each package.
  final Map<String, Version> _neededPackages = {};

  /// 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]).
  NullabilityMigrationImpl(NullabilityMigrationListener listener,
      LineInfo Function(String) getLineInfo,
      {bool permissive = false,
      NullabilityMigrationInstrumentation instrumentation,
      bool removeViaComments = false,
      bool warnOnWeakCode = true})
      : this._(
            listener,
            NullabilityGraph(instrumentation: instrumentation),
            permissive,
            instrumentation,
            removeViaComments,
            warnOnWeakCode,
            getLineInfo);

  NullabilityMigrationImpl._(
      this.listener,
      this._graph,
      this._permissive,
      this._instrumentation,
      this.removeViaComments,
      this.warnOnWeakCode,
      this._getLineInfo) {
    _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.isPathBeingMigrated(entry.key.fullName)) 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,
        _neededPackages);
    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);
    }
  }

  Map<String, Version> finish() {
    _postmortemFileWriter?.write();
    _instrumentation?.finished();
    return _neededPackages;
  }

  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,
          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 startLocation = lineInfo.getLocation(edit.offset);
    final endLocation = lineInfo.getLocation(edit.end);
    var location = Location(
      source.fullName,
      edit.offset,
      edit.length,
      startLocation.lineNumber,
      startLocation.columnNumber,
      endLocation.lineNumber,
      endLocation.columnNumber,
    );
    return location;
  }

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