// 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/analysis_server.dart';
import 'package:analysis_server/src/collections.dart';
import 'package:analysis_server/src/domain_abstract.dart';
import 'package:analysis_server/src/domains/completion/available_suggestions.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_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/token_details/token_detail_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/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/util/performance/operation_performance.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:analyzer_plugin/utilities/change_builder/change_builder_core.dart';

/// Instances of the class [CompletionDomainHandler] implement a
/// [RequestHandler] that handles requests in the completion domain.
class CompletionDomainHandler extends AbstractRequestHandler {
  /// The maximum number of performance measurements to keep.
  static const int performanceListMaxLength = 50;

  /// The completion services that the client is currently subscribed.
  final Set<CompletionService> subscriptions = <CompletionService>{};

  /// The next completion response id.
  int _nextCompletionId = 0;

  /// Code completion performance for the last completion operation.
  CompletionPerformance performance;

  /// A list of code completion performance measurements for the latest
  /// completion operation up to [performanceListMaxLength] measurements.
  final RecentBuffer<CompletionPerformance> performanceList =
      RecentBuffer<CompletionPerformance>(performanceListMaxLength);

  /// The current request being processed or `null` if none.
  CompletionRequestImpl _currentRequest;

  /// The identifiers of the latest `getSuggestionDetails` request.
  /// We use it to abort previous requests.
  int _latestGetSuggestionDetailsId = 0;

  /// Initialize a new request handler for the given [server].
  CompletionDomainHandler(AnalysisServer server) : 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<CompletionResult> computeSuggestions(
    OperationPerformanceImpl perf,
    CompletionRequestImpl request,
    CompletionGetSuggestionsParams params,
    Set<ElementKind> includedElementKinds,
    Set<String> includedElementNames,
    List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags,
  ) async {
    //
    // Allow plugins to start computing fixes.
    //
    Map<PluginInfo, Future<plugin.Response>> pluginFutures;
    plugin.CompletionGetSuggestionsParams requestParams;
    var file = params.file;
    var offset = params.offset;
    var driver = server.getAnalysisDriver(file);
    if (driver != null) {
      requestParams = plugin.CompletionGetSuggestionsParams(file, offset);
      pluginFutures = server.pluginManager
          .broadcastRequest(requestParams, contextRoot: driver.contextRoot);
    }
    //
    // Compute completions generated by server.
    //
    var suggestions = <CompletionSuggestion>[];
    if (request.result != null) {
      const COMPUTE_SUGGESTIONS_TAG = 'computeSuggestions';
      await perf.runAsync(COMPUTE_SUGGESTIONS_TAG, (perf) async {
        var manager = DartCompletionManager(
          dartdocDirectiveInfo: server.getDartdocDirectiveInfoFor(
            request.result,
          ),
          includedElementKinds: includedElementKinds,
          includedElementNames: includedElementNames,
          includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
        );

        var contributorTag = 'computeSuggestions - ${manager.runtimeType}';
        await perf.runAsync(contributorTag, (performance) async {
          try {
            suggestions.addAll(
              await manager.computeSuggestions(performance, request),
            );
          } on AbortCompletion {
            suggestions.clear();
          }
        });
      });
    }
    // 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 (pluginFutures != null) {
      var responses = await waitForResponses(pluginFutures,
          requestParameters: requestParams, timeout: 100);
      for (var response in responses) {
        var result =
            plugin.CompletionGetSuggestionsResult.fromResponse(response);
        if (result.results != null && result.results.isNotEmpty) {
          if (suggestions.isEmpty) {
            request.replacementOffset = result.replacementOffset;
            request.replacementLength = result.replacementLength;
          } else if (request.replacementOffset != result.replacementOffset &&
              request.replacementLength != result.replacementLength) {
            server.instrumentationService
                .logError('Plugin completion-results dropped due to conflicting'
                    ' replacement offset/length: ${result.toJson()}');
            continue;
          }
          suggestions.addAll(result.results);
        }
      }
    }
    //
    // Return the result.
    //
    return CompletionResult(
        request.replacementOffset, request.replacementLength, 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;
    if (AnalysisEngine.isAnalysisOptionsFileName(file)) {
      var generator = AnalysisOptionsGenerator(provider);
      return generator.getSuggestions(file, offset);
    }
    var fileName = provider.pathContext.basename(file);
    if (fileName == AnalysisEngine.PUBSPEC_YAML_FILE) {
      var generator = PubspecGenerator(provider);
      return generator.getSuggestions(file, offset);
    } else if (fileName == AnalysisEngine.FIX_DATA_FILE) {
      var generator = FixDataGenerator(provider);
      return generator.getSuggestions(file, offset);
    }
    return const YamlCompletionResults.empty();
  }

  /// Process a `completion.getSuggestionDetails` request.
  void getSuggestionDetails(Request request) async {
    var params = CompletionGetSuggestionDetailsParams.fromRequest(request);

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

    var libraryId = params.id;
    var library = server.declarationsTracker.getLibrary(libraryId);
    if (library == null) {
      server.sendResponse(Response.invalidParameter(
        request,
        'libraryId',
        'No such library: $libraryId',
      ));
      return;
    }

    // The label might be `MyEnum.myValue`, but we import only `MyEnum`.
    var requestedName = params.label;
    if (requestedName.contains('.')) {
      requestedName = requestedName.substring(
        0,
        requestedName.indexOf('.'),
      );
    }

    const timeout = Duration(milliseconds: 1000);
    var timer = Stopwatch()..start();
    var id = ++_latestGetSuggestionDetailsId;
    while (id == _latestGetSuggestionDetailsId && timer.elapsed < timeout) {
      try {
        var analysisDriver = server.getAnalysisDriver(file);
        var session = analysisDriver.currentSession;

        var completion = params.label;
        var builder = ChangeBuilder(session: session);
        await builder.addDartFileEdit(file, (builder) {
          var result = builder.importLibraryElement(library.uri);
          if (result.prefix != null) {
            completion = '${result.prefix}.$completion';
          }
        });

        server.sendResponse(
          CompletionGetSuggestionDetailsResult(
            completion,
            change: builder.sourceChange,
          ).toResponse(request.id),
        );
        return;
      } on InconsistentAnalysisException {
        // Loop around to try again.
      }
    }

    // Timeout or abort, send the empty response.
    server.sendResponse(
      CompletionGetSuggestionDetailsResult('').toResponse(request.id),
    );
  }

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

    return runZonedGuarded(() {
      var requestName = request.method;

      if (requestName == COMPLETION_REQUEST_GET_SUGGESTION_DETAILS) {
        getSuggestionDetails(request);
        return Response.DELAYED_RESPONSE;
      } else if (requestName == COMPLETION_REQUEST_GET_SUGGESTIONS) {
        processRequest(request);
        return Response.DELAYED_RESPONSE;
      } else if (requestName == COMPLETION_REQUEST_LIST_TOKEN_DETAILS) {
        listTokenDetails(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(CompletionRequest completionRequest) {
    if (_currentRequest == completionRequest) {
      _currentRequest = null;
    }
  }

  /// Process a `completion.listTokenDetails` request.
  Future<void> listTokenDetails(Request request) async {
    var params = CompletionListTokenDetailsParams.fromRequest(request);

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

    var analysisDriver = server.getAnalysisDriver(file);
    if (analysisDriver == null) {
      server.sendResponse(Response.invalidParameter(
        request,
        'file',
        'File is not being analyzed: $file',
      ));
    }
    var session = analysisDriver.currentSession;
    var result = await session.getResolvedUnit(file);
    if (result.state != ResultState.VALID) {
      server.sendResponse(Response.invalidParameter(
        request,
        'file',
        'File does not exist or cannot be read: $file',
      ));
    }

    var builder = TokenDetailBuilder();
    builder.visitNode(result.unit);
    server.sendResponse(
      CompletionListTokenDetailsResult(builder.details).toResponse(request.id),
    );
  }

  /// Process a `completion.getSuggestions` request.
  Future<void> processRequest(Request request) async {
    performance = CompletionPerformance();

    await performance.runRequestOperation((perf) async {
      // extract and validate params
      var params = CompletionGetSuggestionsParams.fromRequest(request);
      var file = params.file;
      var offset = params.offset;

      if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
        return;
      }
      if (file.endsWith('.yaml')) {
        // Return the response without results.
        var completionId = (_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;
      }

      var resolvedUnit = await server.getResolvedUnit(file);
      server.requestStatistics?.addItemTimeNow(request, 'resolvedUnit');
      if (resolvedUnit?.state == ResultState.VALID) {
        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;
        }

        recordRequest(performance, file, resolvedUnit.content, offset);
      }
      var completionRequest =
          CompletionRequestImpl(resolvedUnit, offset, performance);

      var completionId = (_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 (subscriptions.contains(CompletionService.AVAILABLE_SUGGESTION_SETS)) {
        includedElementKinds = <ElementKind>{};
        includedElementNames = <String>{};
        includedSuggestionRelevanceTags = <IncludedSuggestionRelevanceTag>[];
      }

      // Compute suggestions in the background
      try {
        var result = await computeSuggestions(
          perf,
          completionRequest,
          params,
          includedElementKinds,
          includedElementNames,
          includedSuggestionRelevanceTags,
        );
        String libraryFile;
        var includedSuggestionSets = <IncludedSuggestionSet>[];
        if (includedElementKinds != null && resolvedUnit != null) {
          libraryFile = resolvedUnit.libraryElement.source.fullName;
          server.sendNotification(
            createExistingImportsNotification(resolvedUnit),
          );
          computeIncludedSetList(
            server.declarationsTracker,
            resolvedUnit,
            includedSuggestionSets,
            includedElementNames,
          );
        }

        const SEND_NOTIFICATION_TAG = 'send notification';
        perf.run(SEND_NOTIFICATION_TAG, (_) {
          sendCompletionNotification(
            completionId,
            result.replacementOffset,
            result.replacementLength,
            result.suggestions,
            libraryFile,
            includedSuggestionSets,
            includedElementKinds?.toList(),
            includedSuggestionRelevanceTags,
          );
        });

        performance.suggestionCount = result.suggestions.length;
      } finally {
        ifMatchesRequestClear(completionRequest);
      }
    });
  }

  /// If tracking code completion performance over time, then
  /// record addition information about the request in the performance record.
  void recordRequest(CompletionPerformance performance, String path,
      String content, int offset) {
    performance.path = path;
    if (performanceListMaxLength == 0) {
      return;
    }
    performance.setContentsAndOffset(content, offset);
    performanceList.add(performance);
  }

  /// Send completion notification results.
  void sendCompletionNotification(
    String completionId,
    int replacementOffset,
    int replacementLength,
    Iterable<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(CompletionRequest completionRequest) {
    _abortCurrentRequest();
    _currentRequest = completionRequest;
  }

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

    subscriptions.clear();
    subscriptions.addAll(params.subscriptions);

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

    return CompletionSetSubscriptionsResult().toResponse(request.id);
  }

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

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