// Copyright (c) 2014, 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:async';

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/domain_abstract.dart';
import 'package:analysis_server/src/domains/completion/available_suggestions.dart';
import 'package:analysis_server/src/handler/legacy/completion_get_suggestion_details.dart';
import 'package:analysis_server/src/handler/legacy/completion_get_suggestion_details2.dart';
import 'package:analysis_server/src/plugin/plugin_manager.dart';
import 'package:analysis_server/src/provisional/completion/completion_core.dart';
import 'package:analysis_server/src/services/completion/completion_performance.dart';
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
import 'package:analysis_server/src/services/completion/dart/fuzzy_filter_sort.dart';
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analysis_server/src/services/completion/yaml/analysis_options_generator.dart';
import 'package:analysis_server/src/services/completion/yaml/fix_data_generator.dart';
import 'package:analysis_server/src/services/completion/yaml/pubspec_generator.dart';
import 'package:analysis_server/src/services/completion/yaml/yaml_completion_generator.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer/src/utilities/cancellation.dart';
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:collection/collection.dart';

/// Instances of the class [CompletionDomainHandler] implement a
/// [RequestHandler] that handles requests in the completion domain.
class CompletionDomainHandler extends AbstractRequestHandler {
  /// Initialize a new request handler for the given [server].
  CompletionDomainHandler(super.server);

  /// Compute completion results for the given request and append them to the
  /// stream. Clients should not call this method directly as it is
  /// automatically called when a client listens to the stream returned by
  /// [results]. Subclasses should override this method, append at least one
  /// result to the [controller], and close the controller stream once complete.
  Future<List<CompletionSuggestionBuilder>> computeSuggestions({
    required CompletionBudget budget,
    required OperationPerformanceImpl performance,
    required DartCompletionRequest request,
    Set<ElementKind>? includedElementKinds,
    Set<String>? includedElementNames,
    List<IncludedSuggestionRelevanceTag>? includedSuggestionRelevanceTags,
    NotImportedSuggestions? notImportedSuggestions,
  }) async {
    //
    // Allow plugins to start computing fixes.
    //
    var requestToPlugins = performance.run('askPlugins', (_) {
      return _sendRequestToPlugins(request);
    });

    //
    // Compute completions generated by server.
    //
    var suggestions = <CompletionSuggestionBuilder>[];
    await performance.runAsync('computeSuggestions', (performance) async {
      var manager = DartCompletionManager(
        budget: budget,
        includedElementKinds: includedElementKinds,
        includedElementNames: includedElementNames,
        includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
        notImportedSuggestions: notImportedSuggestions,
      );

      suggestions.addAll(
        await manager.computeSuggestions(request, performance),
      );
    });
    // TODO (danrubel) if request is obsolete (processAnalysisRequest returns
    // false) then send empty results

    //
    // Add the completions produced by plugins to the server-generated list.
    //
    if (requestToPlugins != null) {
      await performance.runAsync('waitForPlugins', (_) async {
        await _addPluginSuggestions(budget, requestToPlugins, suggestions);
      });
    }

    return suggestions;
  }

  /// Return the suggestions that should be presented in the YAML [file] at the
  /// given [offset].
  YamlCompletionResults computeYamlSuggestions(String file, int offset) {
    var provider = server.resourceProvider;
    var pathContext = provider.pathContext;
    if (file_paths.isAnalysisOptionsYaml(pathContext, file)) {
      var generator = AnalysisOptionsGenerator(provider);
      return generator.getSuggestions(file, offset);
    } else if (file_paths.isFixDataYaml(pathContext, file)) {
      var generator = FixDataGenerator(provider);
      return generator.getSuggestions(file, offset);
    } else if (file_paths.isPubspecYaml(pathContext, file)) {
      var generator = PubspecGenerator(provider, server.pubPackageService);
      return generator.getSuggestions(file, offset);
    }
    return const YamlCompletionResults.empty();
  }

  /// Implement the 'completion.getSuggestions2' request.
  void getSuggestions2(Request request) async {
    var params = CompletionGetSuggestions2Params.fromRequest(request);
    var file = params.file;
    var offset = params.offset;

    var timeoutMilliseconds = params.timeout;
    var budget = CompletionBudget(
      timeoutMilliseconds != null
          ? Duration(milliseconds: timeoutMilliseconds)
          : server.completionState.budgetDuration,
    );

    var provider = server.resourceProvider;
    var pathContext = provider.pathContext;

    if (file.endsWith('.yaml')) {
      final suggestions = computeYamlSuggestions(file, offset);
      server.sendResponse(
        CompletionGetSuggestions2Result(
          suggestions.replacementOffset,
          suggestions.replacementLength,
          suggestions.suggestions,
          false,
        ).toResponse(request.id),
      );
      return;
    }

    if (!file_paths.isDart(pathContext, file)) {
      server.sendResponse(
        CompletionGetSuggestions2Result(offset, 0, [], false)
            .toResponse(request.id),
      );
      return;
    }

    var performance = OperationPerformanceImpl('<root>');
    performance.runAsync(
      'request',
      (performance) async {
        var resolvedUnit = await performance.runAsync(
          'resolveForCompletion',
          (performance) {
            return server.resolveForCompletion(
              path: file,
              offset: offset,
              performance: performance,
            );
          },
        );
        if (resolvedUnit == null) {
          server.sendResponse(Response.fileNotAnalyzed(request, file));
          return;
        }

        if (offset < 0 || offset > resolvedUnit.content.length) {
          server.sendResponse(Response.invalidParameter(
              request,
              'params.offset',
              'Expected offset between 0 and source length inclusive,'
                  ' but found $offset'));
          return;
        }

        final completionPerformance = CompletionPerformance(
          operation: performance,
          path: file,
          content: resolvedUnit.content,
          offset: offset,
        );
        server.completionState.performanceList.add(completionPerformance);

        var analysisSession = resolvedUnit.analysisSession;
        var enclosingNode =
            resolvedUnit.resolvedNodes.lastOrNull ?? resolvedUnit.parsedUnit;

        var completionRequest = DartCompletionRequest(
          analysisSession: analysisSession,
          filePath: resolvedUnit.path,
          fileContent: resolvedUnit.content,
          unitElement: resolvedUnit.unitElement,
          enclosingNode: enclosingNode,
          offset: offset,
          dartdocDirectiveInfo:
              server.getDartdocDirectiveInfoForSession(analysisSession),
          documentationCache:
              server.getDocumentationCacheForSession(analysisSession),
        );
        setNewRequest(completionRequest);

        var notImportedSuggestions = NotImportedSuggestions();
        var suggestionBuilders = <CompletionSuggestionBuilder>[];
        try {
          suggestionBuilders = await computeSuggestions(
            budget: budget,
            performance: performance,
            request: completionRequest,
            notImportedSuggestions: notImportedSuggestions,
          );
        } on AbortCompletion {
          return server.sendResponse(
            CompletionGetSuggestions2Result(
              completionRequest.replacementOffset,
              completionRequest.replacementLength,
              [],
              true,
            ).toResponse(request.id),
          );
        }

        performance.run('filter', (performance) {
          performance.getDataInt('count').add(suggestionBuilders.length);
          suggestionBuilders = fuzzyFilterSort(
            pattern: completionRequest.targetPrefix,
            suggestions: suggestionBuilders,
          );
          performance.getDataInt('matchCount').add(suggestionBuilders.length);
        });

        var lengthRestricted =
            suggestionBuilders.take(params.maxResults).toList();
        completionPerformance.computedSuggestionCount =
            suggestionBuilders.length;
        completionPerformance.transmittedSuggestionCount =
            lengthRestricted.length;

        var suggestions = lengthRestricted.map((e) => e.build()).toList();

        var isIncomplete = notImportedSuggestions.isIncomplete ||
            lengthRestricted.length < suggestionBuilders.length;

        performance.run('sendResponse', (_) {
          server.sendResponse(
            CompletionGetSuggestions2Result(
              completionRequest.replacementOffset,
              completionRequest.replacementLength,
              suggestions,
              isIncomplete,
            ).toResponse(request.id),
          );
        });
      },
    );
  }

  @override
  Response? handleRequest(
      Request request, CancellationToken cancellationToken) {
    if (!server.options.featureSet.completion) {
      return Response.invalidParameter(
        request,
        'request',
        'The completion feature is not enabled',
      );
    }

    return runZonedGuarded<Response?>(() {
      var requestName = request.method;

      if (requestName == COMPLETION_REQUEST_GET_SUGGESTION_DETAILS) {
        CompletionGetSuggestionDetailsHandler(
                server, request, cancellationToken)
            .handle();
        return Response.DELAYED_RESPONSE;
      } else if (requestName == COMPLETION_REQUEST_GET_SUGGESTION_DETAILS2) {
        CompletionGetSuggestionDetails2Handler(
                server, request, cancellationToken)
            .handle();
        return Response.DELAYED_RESPONSE;
      } else if (requestName == COMPLETION_REQUEST_GET_SUGGESTIONS) {
        processRequest(request);
        return Response.DELAYED_RESPONSE;
      } else if (requestName == COMPLETION_REQUEST_GET_SUGGESTIONS2) {
        getSuggestions2(request);
        return Response.DELAYED_RESPONSE;
      } else if (requestName == COMPLETION_REQUEST_SET_SUBSCRIPTIONS) {
        return setSubscriptions(request);
      }
      return null;
    }, (exception, stackTrace) {
      AnalysisEngine.instance.instrumentationService.logException(
          CaughtException.withMessage(
              'Failed to handle completion domain request: ${request.method}',
              exception,
              stackTrace));
    });
  }

  void ifMatchesRequestClear(DartCompletionRequest request) {
    if (server.completionState.currentRequest == request) {
      server.completionState.currentRequest = null;
    }
  }

  /// Process a `completion.getSuggestions` request.
  Future<void> processRequest(Request request) async {
    var budget = CompletionBudget(server.completionState.budgetDuration);

    // extract and validate params
    var params = CompletionGetSuggestionsParams.fromRequest(request);
    var file = params.file;
    var offset = params.offset;

    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
      return;
    }

    var performance = OperationPerformanceImpl('<root>');
    performance.runAsync(
      'request',
      (performance) async {
        if (file.endsWith('.yaml')) {
          // Return the response without results.
          var completionId =
              (server.completionState.nextCompletionId++).toString();
          server.sendResponse(CompletionGetSuggestionsResult(completionId)
              .toResponse(request.id));
          // Send a notification with results.
          final suggestions = computeYamlSuggestions(file, offset);
          sendCompletionNotification(
            completionId,
            suggestions.replacementOffset,
            suggestions.replacementLength,
            suggestions.suggestions,
            null,
            null,
            null,
            null,
          );
          return;
        } else if (!file.endsWith('.dart')) {
          // Return the response without results.
          var completionId =
              (server.completionState.nextCompletionId++).toString();
          server.sendResponse(CompletionGetSuggestionsResult(completionId)
              .toResponse(request.id));
          // Send a notification with results.
          sendCompletionNotification(
              completionId, offset, 0, [], null, null, null, null);
          return;
        }

        var resolvedUnit = await server.getResolvedUnit(file);
        if (resolvedUnit == null) {
          server.sendResponse(Response.fileNotAnalyzed(request, file));
          return;
        }

        server.requestStatistics?.addItemTimeNow(request, 'resolvedUnit');

        if (offset < 0 || offset > resolvedUnit.content.length) {
          server.sendResponse(Response.invalidParameter(
              request,
              'params.offset',
              'Expected offset between 0 and source length inclusive,'
                  ' but found $offset'));
          return;
        }

        final completionPerformance = CompletionPerformance(
          operation: performance,
          path: file,
          content: resolvedUnit.content,
          offset: offset,
        );
        server.completionState.performanceList.add(completionPerformance);

        var declarationsTracker = server.declarationsTracker;
        if (declarationsTracker == null) {
          server.sendResponse(Response.unsupportedFeature(
              request.id, 'Completion is not enabled.'));
          return;
        }

        var completionRequest = DartCompletionRequest.forResolvedUnit(
          resolvedUnit: resolvedUnit,
          offset: offset,
          dartdocDirectiveInfo: server.getDartdocDirectiveInfoFor(
            resolvedUnit,
          ),
          documentationCache: server.getDocumentationCacheFor(resolvedUnit),
        );

        var completionId =
            (server.completionState.nextCompletionId++).toString();

        setNewRequest(completionRequest);

        // initial response without results
        server.sendResponse(CompletionGetSuggestionsResult(completionId)
            .toResponse(request.id));

        // If the client opted into using available suggestion sets,
        // create the kinds set, so signal the completion manager about opt-in.
        Set<ElementKind>? includedElementKinds;
        Set<String>? includedElementNames;
        List<IncludedSuggestionRelevanceTag>? includedSuggestionRelevanceTags;
        if (server.completionState.subscriptions
            .contains(CompletionService.AVAILABLE_SUGGESTION_SETS)) {
          includedElementKinds = <ElementKind>{};
          includedElementNames = <String>{};
          includedSuggestionRelevanceTags = <IncludedSuggestionRelevanceTag>[];
        }

        // Compute suggestions in the background
        try {
          var suggestionBuilders = <CompletionSuggestionBuilder>[];
          try {
            suggestionBuilders = await computeSuggestions(
              budget: budget,
              performance: performance,
              request: completionRequest,
              includedElementKinds: includedElementKinds,
              includedElementNames: includedElementNames,
              includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
            );
          } on AbortCompletion {
            // Continue with empty suggestions list.
          }
          String? libraryFile;
          var includedSuggestionSets = <IncludedSuggestionSet>[];
          if (includedElementKinds != null && includedElementNames != null) {
            libraryFile = resolvedUnit.libraryElement.source.fullName;
            server.sendNotification(
              createExistingImportsNotification(resolvedUnit),
            );
            computeIncludedSetList(
              declarationsTracker,
              completionRequest,
              includedSuggestionSets,
              includedElementNames,
            );
          }

          const SEND_NOTIFICATION_TAG = 'send notification';
          performance.run(SEND_NOTIFICATION_TAG, (_) {
            sendCompletionNotification(
              completionId,
              completionRequest.replacementOffset,
              completionRequest.replacementLength,
              suggestionBuilders.map((e) => e.build()).toList(),
              libraryFile,
              includedSuggestionSets,
              includedElementKinds?.toList(),
              includedSuggestionRelevanceTags,
            );
          });

          completionPerformance.computedSuggestionCount =
              suggestionBuilders.length;
          completionPerformance.transmittedSuggestionCount =
              suggestionBuilders.length;
        } finally {
          ifMatchesRequestClear(completionRequest);
        }
      },
    );
  }

  /// Send completion notification results.
  void sendCompletionNotification(
    String completionId,
    int replacementOffset,
    int replacementLength,
    List<CompletionSuggestion> results,
    String? libraryFile,
    List<IncludedSuggestionSet>? includedSuggestionSets,
    List<ElementKind>? includedElementKinds,
    List<IncludedSuggestionRelevanceTag>? includedSuggestionRelevanceTags,
  ) {
    server.sendNotification(
      CompletionResultsParams(
        completionId,
        replacementOffset,
        replacementLength,
        results,
        true,
        libraryFile: libraryFile,
        includedSuggestionSets: includedSuggestionSets,
        includedElementKinds: includedElementKinds,
        includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
      ).toNotification(),
    );
  }

  void setNewRequest(DartCompletionRequest request) {
    _abortCurrentRequest();
    server.completionState.currentRequest = request;
  }

  /// Implement the 'completion.setSubscriptions' request.
  Response setSubscriptions(Request request) {
    var params = CompletionSetSubscriptionsParams.fromRequest(request);

    var subscriptions = server.completionState.subscriptions;
    subscriptions.clear();
    subscriptions.addAll(params.subscriptions);

    var data = server.declarationsTrackerData;
    if (data != null) {
      if (subscriptions.contains(CompletionService.AVAILABLE_SUGGESTION_SETS)) {
        var soFarLibraries = data.startListening((change) {
          server.sendNotification(
            createCompletionAvailableSuggestionsNotification(
              change.changed,
              change.removed,
            ),
          );
        });
        server.sendNotification(
          createCompletionAvailableSuggestionsNotification(
            soFarLibraries,
            [],
          ),
        );
      } else {
        data.stopListening();
      }
    }
    return CompletionSetSubscriptionsResult().toResponse(request.id);
  }

  /// Abort the current completion request, if any.
  void _abortCurrentRequest() {
    var currentRequest = server.completionState.currentRequest;
    if (currentRequest != null) {
      currentRequest.abort();
      server.completionState.currentRequest = null;
    }
  }

  /// Add the completions produced by plugins to the server-generated list.
  Future<void> _addPluginSuggestions(
    CompletionBudget budget,
    _RequestToPlugins requestToPlugins,
    List<CompletionSuggestionBuilder> suggestionBuilders,
  ) async {
    var responses = await waitForResponses(
      requestToPlugins.futures,
      requestParameters: requestToPlugins.parameters,
      timeout: budget.left,
    );
    for (var response in responses) {
      var result = plugin.CompletionGetSuggestionsResult.fromResponse(response);
      if (result.results.isNotEmpty) {
        var completionRequest = requestToPlugins.completionRequest;
        if (completionRequest.replacementOffset != result.replacementOffset &&
            completionRequest.replacementLength != result.replacementLength) {
          server.instrumentationService
              .logError('Plugin completion-results dropped due to conflicting'
                  ' replacement offset/length: ${result.toJson()}');
          continue;
        }
        suggestionBuilders.addAll(
          result.results.map(
            (suggestion) => ValueCompletionSuggestionBuilder(suggestion),
          ),
        );
      }
    }
  }

  /// Send the completion request to plugins, so that they work in other
  /// isolates in parallel with the server isolate.
  _RequestToPlugins? _sendRequestToPlugins(
    DartCompletionRequest completionRequest,
  ) {
    var pluginRequestParameters = plugin.CompletionGetSuggestionsParams(
      completionRequest.path,
      completionRequest.offset,
    );

    return _RequestToPlugins(
      completionRequest: completionRequest,
      parameters: pluginRequestParameters,
      futures: server.pluginManager.broadcastRequest(
        pluginRequestParameters,
        contextRoot: completionRequest.analysisContext.contextRoot,
      ),
    );
  }
}

/// The result of computing suggestions for code completion.
class CompletionResult {
  /// The length of the text to be replaced if the remainder of the identifier
  /// containing the cursor is to be replaced when the suggestion is applied
  /// (that is, the number of characters in the existing identifier).
  final int replacementLength;

  /// The offset of the start of the text to be replaced. This will be different
  /// than the offset used to request the completion suggestions if there was a
  /// portion of an identifier before the original offset. In particular, the
  /// replacementOffset will be the offset of the beginning of said identifier.
  final int replacementOffset;

  /// The suggested completions.
  final List<CompletionSuggestion> suggestions;

  CompletionResult(
      this.replacementOffset, this.replacementLength, this.suggestions);
}

class _RequestToPlugins {
  final DartCompletionRequest completionRequest;
  final plugin.CompletionGetSuggestionsParams parameters;
  final Map<PluginInfo, Future<plugin.Response>> futures;

  _RequestToPlugins({
    required this.completionRequest,
    required this.parameters,
    required this.futures,
  });
}
