// Copyright (c) 2018, 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/lsp_protocol/protocol.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analysis_server/src/plugin/plugin_manager.dart';
import 'package:analysis_server/src/protocol_server.dart' hide Position;
import 'package:analysis_server/src/services/correction/assist.dart';
import 'package:analysis_server/src/services/correction/assist_internal.dart';
import 'package:analysis_server/src/services/correction/change_workspace.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analysis_server/src/services/correction/fix_internal.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart'
    show InconsistentAnalysisException;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:collection/collection.dart' show groupBy;

class CodeActionHandler extends MessageHandler<CodeActionParams,
    List<Either2<Command, CodeAction>>> {
  // Because server+plugin results are different types and we lose
  // priorites when converting them to CodeActions, store the priorities
  // against each action in an expando. This avoids wrapping CodeActions in
  // another wrapper class (since we can't modify the LSP-spec-generated
  // CodeAction class).
  final codeActionPriorities = Expando<int>();

  /// A comparator that can be used to sort [CodeActions]s using priorities
  /// in [codeActionPriorities].
  ///
  /// The highest number priority will be sorted before lower number priorities.
  /// Items with the same priority are sorted alphabetically by their title.
  late final Comparator<CodeAction> _codeActionComparator =
      (CodeAction a, CodeAction b) {
    // We should never be sorting actions without priorities.
    final aPriority = codeActionPriorities[a] ?? 0;
    final bPriority = codeActionPriorities[b] ?? 0;
    if (aPriority != bPriority) {
      return bPriority - aPriority;
    }
    return a.title.compareTo(b.title);
  };

  CodeActionHandler(super.server);

  @override
  Method get handlesMessage => Method.textDocument_codeAction;

  @override
  LspJsonHandler<CodeActionParams> get jsonHandler =>
      CodeActionParams.jsonHandler;

  @override
  Future<ErrorOr<List<Either2<Command, CodeAction>>>> handle(
      CodeActionParams params,
      MessageInfo message,
      CancellationToken token) async {
    if (!isDartDocument(params.textDocument)) {
      return success(const []);
    }

    final path = pathOfDoc(params.textDocument);
    if (!path.isError && !server.isAnalyzed(path.result)) {
      return success(const []);
    }

    final clientCapabilities = server.clientCapabilities;
    if (clientCapabilities == null) {
      // This should not happen unless a client misbehaves.
      return serverNotInitializedError;
    }

    final supportsApplyEdit = clientCapabilities.applyEdit;
    final supportsLiteralCodeActions = clientCapabilities.literalCodeActions;
    final supportedKinds = clientCapabilities.codeActionKinds;
    final supportedDiagnosticTags = clientCapabilities.diagnosticTags;

    final unit = await path.mapResult(requireResolvedUnit);

    /// Whether a fix of kind [kind] should be included in the results.
    ///
    /// Unlike [shouldIncludeAnyOfKind], this function is called with a more
    /// specific action kind and answers the question "Should we include this
    /// specific fix kind?".
    bool shouldIncludeKind(CodeActionKind? kind) {
      /// Checks whether the kind matches the [wanted] kind.
      ///
      /// If `wanted` is `refactor.foo` then:
      ///  - refactor.foo - included
      ///  - refactor.foobar - not included
      ///  - refactor.foo.bar - included
      bool isMatch(CodeActionKind wanted) =>
          kind == wanted || kind.toString().startsWith('$wanted.');

      // If the client wants only a specific set, use only that filter.
      final only = params.context.only;
      if (only != null) {
        return only.any(isMatch);
      }

      // Otherwise, filter out anything not supported by the client (if they
      // advertised that they provided the kinds).
      if (supportsLiteralCodeActions && !supportedKinds.any(isMatch)) {
        return false;
      }

      return true;
    }

    /// Whether any fixes of kind [kind] should be included in the results.
    ///
    /// Unlike [shouldIncludeKind], this function is called with a more general
    /// action kind and answers the question "Should we include any actions of
    /// kind CodeActionKind.Source?".
    bool shouldIncludeAnyOfKind(CodeActionKind? kind) {
      /// Checks whether the kind matches the [wanted] kind.
      ///
      /// If `kind` is `refactor.foo` then for these `wanted` values:
      ///  - wanted=refactor.foo - true
      ///  - wanted=refactor.foo.bar - true
      ///  - wanted=refactor - false
      ///  - wanted=refactor.bar - false
      bool isMatch(CodeActionKind wanted) =>
          kind == wanted || wanted.toString().startsWith('$kind.');

      final only = params.context.only;
      if (only != null) {
        return only.any(isMatch);
      }

      return true;
    }

    return unit.mapResult((unit) {
      final startOffset = toOffset(unit.lineInfo, params.range.start);
      final endOffset = toOffset(unit.lineInfo, params.range.end);
      return startOffset.mapResult((startOffset) {
        return endOffset.mapResult((endOffset) {
          final offset = startOffset;
          final length = endOffset - startOffset;
          return message.performance.runAsync(
            'getCodeActions',
            (performance) => _getCodeActions(
              performance,
              shouldIncludeKind,
              shouldIncludeAnyOfKind,
              supportsLiteralCodeActions,
              supportsApplyEdit,
              supportedDiagnosticTags,
              path.result,
              params.range,
              offset,
              length,
              unit,
              params.context.triggerKind,
            ),
          );
        });
      });
    });
  }

  /// Creates a comparer for [CodeActions] that compares the column distance from [pos].
  int Function(CodeAction a, CodeAction b) _codeActionColumnDistanceComparer(
      Position pos) {
    Position posOf(CodeAction action) {
      final diagnostics = action.diagnostics;
      return diagnostics != null && diagnostics.isNotEmpty
          ? diagnostics.first.range.start
          : pos;
    }

    return (a, b) => _columnDistance(posOf(a), pos)
        .compareTo(_columnDistance(posOf(b), pos));
  }

  /// Returns the distance (in columns, ignoring lines) between two positions.
  int _columnDistance(Position a, Position b) =>
      (a.character - b.character).abs();

  /// Wraps a command in a CodeAction if the client supports it so that a
  /// CodeActionKind can be supplied.
  Either2<Command, CodeAction> _commandOrCodeAction(
    bool supportsLiteralCodeActions,
    CodeActionKind kind,
    Command command,
  ) {
    return supportsLiteralCodeActions
        ? Either2<Command, CodeAction>.t2(
            CodeAction(title: command.title, kind: kind, command: command),
          )
        : Either2<Command, CodeAction>.t1(command);
  }

  /// Creates a CodeAction to apply this assist. Note: This code will fetch the
  /// version of each document being modified so it's important to call this
  /// immediately after computing edits to ensure the document is not modified
  /// before the version number is read.
  CodeAction _createAssistAction(SourceChange change, ResolvedUnitResult unit) {
    return CodeAction(
      title: change.message,
      kind: toCodeActionKind(change.id, CodeActionKind.Refactor),
      diagnostics: const [],
      edit: createWorkspaceEdit(server, change,
          allowSnippets: true, filePath: unit.path, lineInfo: unit.lineInfo),
    );
  }

  /// Creates a CodeAction to apply this fix. Note: This code will fetch the
  /// version of each document being modified so it's important to call this
  /// immediately after computing edits to ensure the document is not modified
  /// before the version number is read.
  CodeAction _createFixAction(
      SourceChange change, Diagnostic diagnostic, ResolvedUnitResult unit) {
    return CodeAction(
      title: change.message,
      kind: toCodeActionKind(change.id, CodeActionKind.QuickFix),
      diagnostics: [diagnostic],
      edit: createWorkspaceEdit(server, change,
          allowSnippets: true, filePath: unit.path, lineInfo: unit.lineInfo),
    );
  }

  /// Dedupes/merges actions that have the same title, selecting the one nearest [pos].
  ///
  /// If actions perform the same edit/command, their diagnostics will be merged
  /// together. Otherwise, the additional accounts are just dropped.
  ///
  /// The first diagnostic for an action is used to determine the position (using
  /// its `start`). If there is no diagnostic, it will be treated as being at [pos].
  ///
  /// If multiple actions have the same position, one will arbitrarily be chosen.
  List<CodeAction> _dedupeActions(Iterable<CodeAction> actions, Position pos) {
    final groups = groupBy(actions, (CodeAction action) => action.title);
    return groups.entries.map((entry) {
      final actions = entry.value;

      // If there's only one in the group, just return it.
      if (actions.length == 1) {
        return actions.single;
      }

      // Otherwise, find the action nearest to the caret.
      actions.sort(_codeActionColumnDistanceComparer(pos));
      final first = actions.first;

      // Get any actions with the same fix (edit/command) for merging diagnostics.
      final others = actions.skip(1).where(
            (other) =>
                // Compare either edits or commands based on which the selected action has.
                first.edit != null
                    ? first.edit == other.edit
                    : first.command != null
                        ? first.command == other.command
                        : false,
          );

      // Build a new CodeAction that merges the diagnostics from each same
      // code action onto a single one.
      return CodeAction(
        title: first.title,
        kind: first.kind,
        // Merge diagnostics from all of the matching CodeActions.
        diagnostics: [
          ...?first.diagnostics,
          for (final other in others) ...?other.diagnostics,
        ],
        edit: first.edit,
        command: first.command,
      );
    }).toList();
  }

  Future<List<Either2<Command, CodeAction>>> _getAssistActions(
    bool Function(CodeActionKind?) shouldIncludeKind,
    bool supportsLiteralCodeActions,
    String path,
    Range range,
    int offset,
    int length,
    ResolvedUnitResult unit,
  ) async {
    try {
      var context = DartAssistContextImpl(
        server.instrumentationService,
        DartChangeWorkspace(
          await server.currentSessions,
        ),
        unit,
        offset,
        length,
      );
      final processor = AssistProcessor(context);
      final serverFuture = processor.compute();
      final pluginFuture = _getPluginAssistChanges(path, offset, length);

      final assists = await serverFuture;
      final pluginChanges = await pluginFuture;

      final codeActions = <CodeAction>[];
      codeActions.addAll(assists.map((assist) {
        final action = _createAssistAction(assist.change, unit);
        codeActionPriorities[action] = assist.kind.priority;
        return action;
      }));
      codeActions.addAll(pluginChanges.map((change) {
        final action = _createAssistAction(change.change, unit);
        codeActionPriorities[action] = change.priority;
        return action;
      }));

      final dedupedCodeActions = _dedupeActions(codeActions, range.start);
      dedupedCodeActions.sort(_codeActionComparator);

      return dedupedCodeActions
          .where((action) => shouldIncludeKind(action.kind))
          .map((action) => Either2<Command, CodeAction>.t2(action))
          .toList();
    } on InconsistentAnalysisException {
      // If an InconsistentAnalysisException occurs, it's likely the user modified
      // the source and therefore is no longer interested in the results, so
      // just return an empty set.
      return [];
    }
  }

  Future<ErrorOr<List<Either2<Command, CodeAction>>>> _getCodeActions(
    OperationPerformanceImpl performance,
    bool Function(CodeActionKind?) shouldIncludeKind,
    bool Function(CodeActionKind?) shouldIncludeAnyOfKind,
    bool supportsLiterals,
    bool supportsWorkspaceApplyEdit,
    Set<DiagnosticTag> supportedDiagnosticTags,
    String path,
    Range range,
    int offset,
    int length,
    ResolvedUnitResult unit,
    CodeActionTriggerKind? triggerKind,
  ) async {
    final docIdentifier = server.getVersionedDocumentIdentifier(path);

    final results = await Future.wait([
      if (shouldIncludeAnyOfKind(CodeActionKind.Source))
        performance.runAsync(
          '_getSourceActions',
          (_) => _getSourceActions(shouldIncludeKind, supportsLiterals,
              supportsWorkspaceApplyEdit, path, triggerKind),
        ),
      // Assists go under the Refactor CodeActionKind so check that here.
      if (shouldIncludeAnyOfKind(CodeActionKind.Refactor))
        performance.runAsync(
          '_getAssistActions',
          (_) => _getAssistActions(shouldIncludeKind, supportsLiterals, path,
              range, offset, length, unit),
        ),
      if (shouldIncludeAnyOfKind(CodeActionKind.Refactor))
        performance.runAsync(
          '_getRefactorActions',
          (_) => _getRefactorActions(shouldIncludeKind, supportsLiterals, path,
              docIdentifier, offset, length, unit),
        ),
      if (shouldIncludeAnyOfKind(CodeActionKind.QuickFix))
        performance.runAsync(
          '_getFixActions',
          (_) => _getFixActions(shouldIncludeKind, supportsLiterals, path,
              offset, supportedDiagnosticTags, range, unit),
        ),
    ]);
    final flatResults = results.expand((x) => x).toList();

    return success(flatResults);
  }

  Future<List<Either2<Command, CodeAction>>> _getFixActions(
    bool Function(CodeActionKind?) shouldIncludeKind,
    bool supportsLiteralCodeActions,
    String path,
    int offset,
    Set<DiagnosticTag> supportedDiagnosticTags,
    Range range,
    ResolvedUnitResult unit,
  ) async {
    final clientSupportsCodeDescription =
        server.clientCapabilities?.diagnosticCodeDescription ?? false;
    // TODO(dantup): We may be missing fixes for pubspec, analysis_options,
    //   android manifests (see _computeServerErrorFixes in EditDomainHandler).
    final lineInfo = unit.lineInfo;
    final codeActions = <CodeAction>[];
    final fixContributor = DartFixContributor();

    final pluginFuture = _getPluginFixActions(unit, offset);

    try {
      var workspace = DartChangeWorkspace(
        await server.currentSessions,
      );
      for (final error in unit.errors) {
        // Server lineNumber is one-based so subtract one.
        var errorLine = lineInfo.getLocation(error.offset).lineNumber - 1;
        if (errorLine < range.start.line || errorLine > range.end.line) {
          continue;
        }
        var context = DartFixContextImpl(
            server.instrumentationService, workspace, unit, error);
        final fixes = await fixContributor.computeFixes(context);
        if (fixes.isNotEmpty) {
          final diagnostic = toDiagnostic(
            unit,
            error,
            supportedTags: supportedDiagnosticTags,
            clientSupportsCodeDescription: clientSupportsCodeDescription,
          );
          codeActions.addAll(
            fixes.map((fix) {
              final action = _createFixAction(fix.change, diagnostic, unit);
              codeActionPriorities[action] = fix.kind.priority;
              return action;
            }),
          );
        }
      }

      Diagnostic pluginErrorToDiagnostic(AnalysisError error) {
        return pluginToDiagnostic(
          (_) => lineInfo,
          error,
          supportedTags: supportedDiagnosticTags,
          clientSupportsCodeDescription: clientSupportsCodeDescription,
        );
      }

      final pluginFixes = await pluginFuture;
      final pluginFixActions = pluginFixes.expand(
        (fix) => fix.fixes.map((fixChange) {
          final action = _createFixAction(
              fixChange.change, pluginErrorToDiagnostic(fix.error), unit);
          codeActionPriorities[action] = fixChange.priority;
          return action;
        }),
      );
      codeActions.addAll(pluginFixActions);

      final dedupedActions = _dedupeActions(codeActions, range.start);
      dedupedActions.sort(_codeActionComparator);

      return dedupedActions
          .where((action) => shouldIncludeKind(action.kind))
          .map((action) => Either2<Command, CodeAction>.t2(action))
          .toList();
    } on InconsistentAnalysisException {
      // If an InconsistentAnalysisException occurs, it's likely the user modified
      // the source and therefore is no longer interested in the results, so
      // just return an empty set.
      return [];
    }
  }

  Future<Iterable<plugin.PrioritizedSourceChange>> _getPluginAssistChanges(
      String path, int offset, int length) async {
    final requestParams = plugin.EditGetAssistsParams(path, offset, length);
    final driver = server.getAnalysisDriver(path);

    Map<PluginInfo, Future<plugin.Response>> pluginFutures;
    if (driver == null) {
      pluginFutures = <PluginInfo, Future<plugin.Response>>{};
    } else {
      pluginFutures = server.pluginManager.broadcastRequest(
        requestParams,
        contextRoot: driver.analysisContext!.contextRoot,
      );
    }

    final pluginChanges = <plugin.PrioritizedSourceChange>[];
    final responses =
        await waitForResponses(pluginFutures, requestParameters: requestParams);

    for (final response in responses) {
      final result = plugin.EditGetAssistsResult.fromResponse(response);
      pluginChanges.addAll(result.assists);
    }

    return pluginChanges;
  }

  Future<Iterable<plugin.AnalysisErrorFixes>> _getPluginFixActions(
      ResolvedUnitResult unit, int offset) async {
    final file = unit.path;
    final requestParams = plugin.EditGetFixesParams(file, offset);
    final driver = server.getAnalysisDriver(file);

    Map<PluginInfo, Future<plugin.Response>> pluginFutures;
    if (driver == null) {
      pluginFutures = <PluginInfo, Future<plugin.Response>>{};
    } else {
      pluginFutures = server.pluginManager.broadcastRequest(
        requestParams,
        contextRoot: driver.analysisContext!.contextRoot,
      );
    }

    final pluginFixes = <plugin.AnalysisErrorFixes>[];
    final responses =
        await waitForResponses(pluginFutures, requestParameters: requestParams);

    for (final response in responses) {
      final result = plugin.EditGetFixesResult.fromResponse(response);
      pluginFixes.addAll(result.fixes);
    }

    return pluginFixes;
  }

  Future<List<Either2<Command, CodeAction>>> _getRefactorActions(
    bool Function(CodeActionKind) shouldIncludeKind,
    bool supportsLiteralCodeActions,
    String path,
    OptionalVersionedTextDocumentIdentifier docIdentifier,
    int offset,
    int length,
    ResolvedUnitResult unit,
  ) async {
    // The refactor actions supported are only valid for Dart files.
    var pathContext = server.resourceProvider.pathContext;
    if (!file_paths.isDart(pathContext, path)) {
      return const [];
    }

    /// Helper to create refactors that execute commands provided with
    /// the current file, location and document version.
    Either2<Command, CodeAction> createRefactor(
      CodeActionKind actionKind,
      String name,
      RefactoringKind refactorKind, [
      Map<String, dynamic>? options,
    ]) {
      return _commandOrCodeAction(
          supportsLiteralCodeActions,
          actionKind,
          Command(
            title: name,
            command: Commands.performRefactor,
            arguments: [
              // TODO(dantup): Change this to a Map once Dart-Code is updated
              //   to handle both Maps and Lists (and some reasonable time has
              //   passed to not worry about old versions).
              refactorKind.toJson(),
              path,
              server.getVersionedDocumentIdentifier(path).version,
              offset,
              length,
              options,
            ],
          ));
    }

    try {
      final refactorActions = <Either2<Command, CodeAction>>[];

      // Extracts
      if (shouldIncludeKind(CodeActionKind.RefactorExtract)) {
        // Extract Method
        if (ExtractMethodRefactoring(server.searchEngine, unit, offset, length)
            .isAvailable()) {
          refactorActions.add(createRefactor(CodeActionKind.RefactorExtract,
              'Extract Method', RefactoringKind.EXTRACT_METHOD));
        }

        // Extract Local Variable
        if (ExtractLocalRefactoring(unit, offset, length).isAvailable()) {
          refactorActions.add(createRefactor(
              CodeActionKind.RefactorExtract,
              'Extract Local Variable',
              RefactoringKind.EXTRACT_LOCAL_VARIABLE));
        }

        // Extract Widget
        if (ExtractWidgetRefactoring(server.searchEngine, unit, offset, length)
            .isAvailable()) {
          refactorActions.add(createRefactor(CodeActionKind.RefactorExtract,
              'Extract Widget', RefactoringKind.EXTRACT_WIDGET));
        }
      }

      // Inlines
      if (shouldIncludeKind(CodeActionKind.RefactorInline)) {
        // Inline Local Variable
        if (InlineLocalRefactoring(server.searchEngine, unit, offset)
            .isAvailable()) {
          refactorActions.add(createRefactor(CodeActionKind.RefactorInline,
              'Inline Local Variable', RefactoringKind.INLINE_LOCAL_VARIABLE));
        }

        // Inline Method
        if (InlineMethodRefactoring(server.searchEngine, unit, offset)
            .isAvailable()) {
          refactorActions.add(createRefactor(CodeActionKind.RefactorInline,
              'Inline Method', RefactoringKind.INLINE_METHOD));
        }
      }

      // Converts/Rewrites
      if (shouldIncludeKind(CodeActionKind.RefactorRewrite)) {
        final node = NodeLocator(offset).searchWithin(unit.unit);
        final element = server.getElementOfNode(node);
        // Getter to Method
        if (element is PropertyAccessorElement) {
          refactorActions.add(createRefactor(
              CodeActionKind.RefactorRewrite,
              'Convert Getter to Method',
              RefactoringKind.CONVERT_GETTER_TO_METHOD));
        }

        // Method to Getter
        if (element is ExecutableElement &&
            element is! PropertyAccessorElement) {
          refactorActions.add(createRefactor(
              CodeActionKind.RefactorRewrite,
              'Convert Method to Getter',
              RefactoringKind.CONVERT_METHOD_TO_GETTER));
        }
      }

      return refactorActions;
    } on InconsistentAnalysisException {
      // If an InconsistentAnalysisException occurs, it's likely the user modified
      // the source and therefore is no longer interested in the results, so
      // just return an empty set.
      return [];
    }
  }

  /// Gets "Source" CodeActions, which are actions that apply to whole files of
  /// source such as Sort Members and Organise Imports.
  Future<List<Either2<Command, CodeAction>>> _getSourceActions(
    bool Function(CodeActionKind) shouldIncludeKind,
    bool supportsLiteralCodeActions,
    bool supportsApplyEdit,
    String path,
    CodeActionTriggerKind? triggerKind,
  ) async {
    // The source actions supported are only valid for Dart files.
    var pathContext = server.resourceProvider.pathContext;
    if (!file_paths.isDart(pathContext, path)) {
      return const [];
    }

    // If the client does not support workspace/applyEdit, we won't be able to
    // run any of these.
    if (!supportsApplyEdit) {
      return const [];
    }

    final autoTriggered = triggerKind == CodeActionTriggerKind.Automatic;

    return [
      if (shouldIncludeKind(DartCodeActionKind.SortMembers))
        _commandOrCodeAction(
          supportsLiteralCodeActions,
          DartCodeActionKind.SortMembers,
          Command(
              title: 'Sort Members',
              command: Commands.sortMembers,
              arguments: [
                {
                  'path': path,
                  if (autoTriggered) 'autoTriggered': true,
                }
              ]),
        ),
      if (shouldIncludeKind(CodeActionKind.SourceOrganizeImports))
        _commandOrCodeAction(
          supportsLiteralCodeActions,
          CodeActionKind.SourceOrganizeImports,
          Command(
              title: 'Organize Imports',
              command: Commands.organizeImports,
              arguments: [
                {
                  'path': path,
                  if (autoTriggered) 'autoTriggered': true,
                }
              ]),
        ),
      if (shouldIncludeKind(DartCodeActionKind.FixAll))
        _commandOrCodeAction(
          supportsLiteralCodeActions,
          DartCodeActionKind.FixAll,
          Command(
            title: 'Fix All',
            command: Commands.fixAll,
            arguments: [
              {
                'path': path,
                if (autoTriggered) 'autoTriggered': true,
              }
            ],
          ),
        ),
    ];
  }
}
