// Copyright (c) 2020, 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:analysis_server/plugin/edit/fix/fix_dart.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/services/correction/change_workspace.dart';
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analysis_server/src/services/correction/dart/data_driven.dart';
import 'package:analysis_server/src/services/correction/dart/organize_imports.dart';
import 'package:analysis_server/src/services/correction/dart/remove_unused_import.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/transform_override_set.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/transform_override_set_parser.dart';
import 'package:analysis_server/src/services/correction/fix_internal.dart';
import 'package:analysis_server/src/services/linter/lint_names.dart';
import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/instrumentation/service.dart';
import 'package:analyzer/source/error_processor.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/change_builder/conflicting_edit_exception.dart';

/// A fix producer that produces changes that will fix multiple diagnostics in
/// one or more files.
///
/// Each diagnostic should have a single fix (correction producer) associated
/// with it except in cases where at most one of the given producers will ever
/// produce a fix.
///
/// The correction producers that are associated with the diagnostics should not
/// produce changes that alter the semantics of the code.
class BulkFixProcessor {
  /// A map from an error code to a list of generators used to create multiple
  /// correction producers used to build fixes for those diagnostics. The
  /// generators used for lint rules are in the [lintMultiProducerMap].
  ///
  /// The expectation is that only one of the correction producers will produce
  /// a change for a given fix. If more than one change is produced the result
  /// will almost certainly be invalid code.
  static const Map<ErrorCode, List<MultiProducerGenerator>>
      nonLintMultiProducerMap = {
    CompileTimeErrorCode.EXTENDS_NON_CLASS: [
      DataDriven.new,
    ],
    // TODO(brianwilkerson) The following fix fails if an invocation of the
    //  function is the argument that needs to be removed.
    // CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS: [
    //   DataDriven.newInstance,
    // ],
    // TODO(brianwilkerson) The following fix fails if an invocation of the
    //  function is the argument that needs to be updated.
    // CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED: [
    //   DataDriven.newInstance,
    // ],
    CompileTimeErrorCode.IMPLEMENTS_NON_CLASS: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.INVALID_OVERRIDE: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.MIXIN_OF_NON_CLASS: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.UNDEFINED_CLASS: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.UNDEFINED_FUNCTION: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.UNDEFINED_GETTER: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.UNDEFINED_IDENTIFIER: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.UNDEFINED_METHOD: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.UNDEFINED_SETTER: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_EXTENSION: [
      DataDriven.new,
    ],
    CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD: [
      DataDriven.new,
    ],
    HintCode.DEPRECATED_MEMBER_USE: [
      DataDriven.new,
    ],
    HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE: [
      DataDriven.new,
    ],
    HintCode.DEPRECATED_MEMBER_USE_WITH_MESSAGE: [
      DataDriven.new,
    ],
    HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE_WITH_MESSAGE: [
      DataDriven.new,
    ],
    HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD: [
      DataDriven.new,
    ],
  };

  /// The service used to report errors when building fixes.
  final InstrumentationService instrumentationService;

  /// Information about the workspace containing the libraries in which changes
  /// will be produced.
  final DartChangeWorkspace workspace;

  /// A flag indicating whether configuration files should be used to override
  /// the transforms.
  final bool useConfigFiles;

  /// An optional list of diagnostic codes to fix.
  final List<String>? codes;

  /// The change builder used to build the changes required to fix the
  /// diagnostics.
  ChangeBuilder builder;

  /// A map associating libraries to fixes with change counts.
  final ChangeMap changeMap = ChangeMap();

  /// Initialize a newly created processor to create fixes for diagnostics in
  /// libraries in the [workspace].
  BulkFixProcessor(this.instrumentationService, this.workspace,
      {this.useConfigFiles = false, List<String>? codes})
      : builder = ChangeBuilder(workspace: workspace),
        codes = codes?.map((e) => e.toLowerCase()).toList();

  List<BulkFix> get fixDetails {
    var details = <BulkFix>[];
    for (var change in changeMap.libraryMap.entries) {
      var fixes = <BulkFixDetail>[];
      for (var codeEntry in change.value.entries) {
        fixes.add(BulkFixDetail(codeEntry.key, codeEntry.value));
      }
      details.add(BulkFix(change.key, fixes));
    }
    return details;
  }

  /// Return a change builder that has been used to create fixes for the
  /// diagnostics in the libraries in the given [contexts].
  Future<ChangeBuilder> fixErrors(List<AnalysisContext> contexts) async {
    for (var context in contexts) {
      var pathContext = context.contextRoot.resourceProvider.pathContext;
      for (var path in context.contextRoot.analyzedFiles()) {
        if (!file_paths.isDart(pathContext, path) ||
            file_paths.isGenerated(path)) {
          continue;
        }
        var library = await context.currentSession.getResolvedLibrary(path);
        if (library is ResolvedLibraryResult) {
          await _fixErrorsInLibrary(library);
        }
      }
    }

    return builder;
  }

  /// Return a change builder that has been used to create fixes for the
  /// diagnostics in [file] in the given [context].
  Future<ChangeBuilder> fixErrorsForFile(
      AnalysisContext context, String path) async {
    var pathContext = context.contextRoot.resourceProvider.pathContext;

    if (file_paths.isDart(pathContext, path) && !file_paths.isGenerated(path)) {
      var library = await context.currentSession.getResolvedLibrary(path);
      if (library is ResolvedLibraryResult) {
        await _fixErrorsInLibrary(library);
      }
    }

    return builder;
  }

  Future<void> _applyProducer(
      CorrectionProducerContext context, CorrectionProducer producer) async {
    producer.configure(context);
    try {
      var localBuilder = builder.copy();
      await producer.compute(localBuilder);
      builder = localBuilder;
    } on ConflictingEditException {
      // If a conflicting edit was added in [compute], then the [localBuilder]
      // is discarded and we revert to the previous state of the builder.
    }
  }

  /// Use the change [builder] to create fixes for the diagnostics in the
  /// library associated with the analysis [result].
  Future<void> _fixErrorsInLibrary(ResolvedLibraryResult result) async {
    var analysisOptions = result.session.analysisContext.analysisOptions;

    Iterable<AnalysisError> filteredErrors(ResolvedUnitResult result) sync* {
      var errors = result.errors.toList();
      errors.sort((a, b) => a.offset.compareTo(b.offset));
      final codes = this.codes;
      // Only fix errors specified in the `codes` list (if defined) and not
      // filtered out in analysis options.
      for (var error in errors) {
        if (codes != null &&
            !codes.contains(error.errorCode.name.toLowerCase())) {
          continue;
        }
        var processor = ErrorProcessor.getProcessor(analysisOptions, error);
        if (processor == null || processor.severity != null) {
          yield error;
        }
      }
    }

    DartFixContextImpl fixContext(
        ResolvedUnitResult result, AnalysisError diagnostic) {
      return DartFixContextImpl(
        instrumentationService,
        workspace,
        result,
        diagnostic,
      );
    }

    CorrectionProducerContext? correctionContext(
        ResolvedUnitResult result, AnalysisError diagnostic) {
      var overrideSet = _readOverrideSet(result);
      return CorrectionProducerContext.create(
        applyingBulkFixes: true,
        dartFixContext: fixContext(result, diagnostic),
        diagnostic: diagnostic,
        overrideSet: overrideSet,
        resolvedResult: result,
        selectionOffset: diagnostic.offset,
        selectionLength: diagnostic.length,
        workspace: workspace,
      );
    }

    //
    // Attempt to apply the fixes that aren't related to directives.
    //
    for (var unitResult in result.units) {
      var overrideSet = _readOverrideSet(unitResult);
      for (var error in filteredErrors(unitResult)) {
        await _fixSingleError(
            fixContext(unitResult, error), unitResult, error, overrideSet);
      }
    }
    //
    // If there are no such fixes in the defining compilation unit, then apply
    // the fixes related to directives.
    //
    var definingUnit = result.units[0];
    AnalysisError? directivesOrderingError;
    var unusedImportErrors = <AnalysisError>[];
    if (!builder.hasEditsFor(definingUnit.path)) {
      for (var error in filteredErrors(definingUnit)) {
        var errorCode = error.errorCode;
        if (errorCode is LintCode) {
          var lintName = errorCode.name;
          if (lintName == LintNames.directives_ordering) {
            directivesOrderingError = error;
            break;
          }
        } else if (errorCode == HintCode.DUPLICATE_IMPORT ||
            errorCode == HintCode.UNNECESSARY_IMPORT ||
            errorCode == HintCode.UNUSED_IMPORT) {
          unusedImportErrors.add(error);
        }
      }
      if (directivesOrderingError != null) {
        // `OrganizeImports` will also remove some of the unused imports, so we
        // apply it first.
        var context = correctionContext(definingUnit, directivesOrderingError);
        if (context != null) {
          await _generateFix(context, OrganizeImports(),
              directivesOrderingError.errorCode.name);
        }
      } else {
        for (var error in unusedImportErrors) {
          var context = correctionContext(definingUnit, error);
          if (context != null) {
            await _generateFix(
                context, RemoveUnusedImport(), error.errorCode.name);
          }
        }
      }
    }
  }

  /// Use the change [builder] and the [fixContext] to create a fix for the
  /// given [diagnostic] in the compilation unit associated with the analysis
  /// [result].
  Future<void> _fixSingleError(
      DartFixContext fixContext,
      ResolvedUnitResult result,
      AnalysisError diagnostic,
      TransformOverrideSet? overrideSet) async {
    var context = CorrectionProducerContext.create(
      applyingBulkFixes: true,
      dartFixContext: fixContext,
      diagnostic: diagnostic,
      overrideSet: overrideSet,
      resolvedResult: result,
      selectionOffset: diagnostic.offset,
      selectionLength: diagnostic.length,
      workspace: workspace,
    );
    if (context == null) {
      return;
    }

    Future<void> bulkApply(
        List<ProducerGenerator> generators, String codeName) async {
      for (var generator in generators) {
        var producer = generator();
        if (producer.canBeAppliedInBulk) {
          await _generateFix(context, producer, codeName);
        }
      }
    }

    var errorCode = diagnostic.errorCode;
    var codeName = errorCode.name;
    try {
      if (errorCode is LintCode) {
        var generators = FixProcessor.lintProducerMap[codeName] ?? [];
        await bulkApply(generators, codeName);
      } else {
        var generators = FixProcessor.nonLintProducerMap[errorCode] ?? [];
        await bulkApply(generators, codeName);
        var multiGenerators = nonLintMultiProducerMap[errorCode];
        if (multiGenerators != null) {
          for (var multiGenerator in multiGenerators) {
            var multiProducer = multiGenerator();
            multiProducer.configure(context);
            await for (var producer in multiProducer.producers) {
              await _generateFix(context, producer, codeName);
            }
          }
        }
      }
    } catch (e, s) {
      throw CaughtException.withMessage(
          'Exception generating fix for $codeName in ${result.path}', e, s);
    }
  }

  Future<void> _generateFix(CorrectionProducerContext context,
      CorrectionProducer producer, String code) async {
    int computeChangeHash() => (builder as ChangeBuilderImpl).changeHash;

    var oldHash = computeChangeHash();
    await _applyProducer(context, producer);
    var newHash = computeChangeHash();
    if (newHash != oldHash) {
      changeMap.add(context.resolvedResult.path, code.toLowerCase());
    }
  }

  /// Return the override set corresponding to the given [result], or `null` if
  /// there is no corresponding configuration file or the file content isn't a
  /// valid override set.
  TransformOverrideSet? _readOverrideSet(ResolvedUnitResult result) {
    if (useConfigFiles) {
      var provider = result.session.resourceProvider;
      var context = provider.pathContext;
      var dartFileName = result.path;
      var configFileName = '${context.withoutExtension(dartFileName)}.config';
      var configFile = provider.getFile(configFileName);
      try {
        var content = configFile.readAsStringSync();
        var parser = TransformOverrideSetParser(
          ErrorReporter(
            AnalysisErrorListener.NULL_LISTENER,
            configFile.createSource(),
            isNonNullableByDefault: false,
          ),
        );
        return parser.parse(content);
      } on FileSystemException {
        // Fall through to return null.
      }
    }
    return null;
  }
}

/// Maps changes to library paths.
class ChangeMap {
  /// Map of paths to maps of codes to counts.
  final Map<String, Map<String, int>> libraryMap = {};

  /// Add an entry for the given [code] in the given [libraryPath].
  void add(String libraryPath, String code) {
    var changes = libraryMap.putIfAbsent(libraryPath, () => {});
    changes.update(code, (value) => value + 1, ifAbsent: () => 1);
  }
}
