// 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:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.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 = Set<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 =
      new 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(
    CompletionRequestImpl request,
    CompletionGetSuggestionsParams params,
    Set<ElementKind> includedElementKinds,
    List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags,
  ) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    //
    // Allow plugins to start computing fixes.
    //
    Map<PluginInfo, Future<plugin.Response>> pluginFutures;
    plugin.CompletionGetSuggestionsParams requestParams;
    String file = params.file;
    int offset = params.offset;
    AnalysisDriver driver = server.getAnalysisDriver(file);
    if (driver != null) {
      requestParams = new plugin.CompletionGetSuggestionsParams(file, offset);
      pluginFutures = server.pluginManager
          .broadcastRequest(requestParams, contextRoot: driver.contextRoot);
    }
    //
    // Compute completions generated by server.
    //
    List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
    if (request.result != null) {
      const COMPUTE_SUGGESTIONS_TAG = 'computeSuggestions';
      performance.logStartTime(COMPUTE_SUGGESTIONS_TAG);

      var manager = new DartCompletionManager(
        includedElementKinds: includedElementKinds,
        includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
      );

      String contributorTag = 'computeSuggestions - ${manager.runtimeType}';
      performance.logStartTime(contributorTag);
      try {
        suggestions.addAll(await manager.computeSuggestions(request));
      } on AbortCompletion {
        suggestions.clear();
      }
      performance.logElapseTime(contributorTag);
      performance.logElapseTime(COMPUTE_SUGGESTIONS_TAG);
    }
    // TODO (danrubel) if request is obsolete (processAnalysisRequest returns
    // false) then send empty results

    //
    // Add the fixes produced by plugins to the server-generated fixes.
    //
    if (pluginFutures != null) {
      List<plugin.Response> responses = await waitForResponses(pluginFutures,
          requestParameters: requestParams);
      for (plugin.Response response in responses) {
        plugin.CompletionGetSuggestionsResult result =
            new 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 new CompletionResult(
        request.replacementOffset, request.replacementLength, suggestions);
  }

  /**
   * 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 fileElement = await session.getUnitElement(file);
        var libraryPath = fileElement.element.librarySource.fullName;

        var resolvedLibrary = await session.getResolvedLibrary(libraryPath);
        var requestedLibraryElement = await session.getLibraryByUri(
          library.uriStr,
        );

        var requestedElement =
            requestedLibraryElement.exportNamespace.get(requestedName);
        if (requestedElement == null) {
          server.sendResponse(Response.invalidParameter(
            request,
            'label',
            'No such element: $requestedName',
          ));
          return;
        }

        var completion = params.label;
        var builder = DartChangeBuilder(session);
        await builder.addFileEdit(libraryPath, (builder) {
          var result = builder.importLibraryElement(
            targetLibrary: resolvedLibrary,
            targetPath: libraryPath,
            targetOffset: params.offset,
            requestedLibrary: requestedLibraryElement,
            requestedElement: requestedElement,
          );
          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) {
    return runZoned(() {
      String 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;
    }, onError: (exception, stackTrace) {
      server.sendServerErrorNotification(
          'Failed to handle completion domain request: ${request.toJson()}',
          exception,
          stackTrace);
    });
  }

  void ifMatchesRequestClear(CompletionRequest completionRequest) {
    if (_currentRequest == completionRequest) {
      _currentRequest = null;
    }
  }

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

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

    AnalysisDriver analysisDriver = server.getAnalysisDriver(file);
    if (analysisDriver == null) {
      server.sendResponse(Response.invalidParameter(
        request,
        'file',
        'File is not being analyzed: $file',
      ));
    }
    AnalysisSession session = analysisDriver.currentSession;
    ResolvedUnitResult 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',
      ));
    }

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

  /**
   * Process a `completion.getSuggestions` request.
   */
  Future<void> processRequest(Request request) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    performance = new CompletionPerformance();

    // extract and validate params
    CompletionGetSuggestionsParams params =
        new CompletionGetSuggestionsParams.fromRequest(request);
    String file = params.file;
    int offset = params.offset;

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

    ResolvedUnitResult resolvedUnit = await server.getResolvedUnit(file);
    if (resolvedUnit?.state == ResultState.VALID) {
      if (offset < 0 || offset > resolvedUnit.content.length) {
        server.sendResponse(new Response.invalidParameter(
            request,
            'params.offset',
            'Expected offset between 0 and source length inclusive,'
            ' but found $offset'));
        return;
      }

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

    String completionId = (_nextCompletionId++).toString();

    setNewRequest(completionRequest);

    // initial response without results
    server.sendResponse(new 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;
    List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags;
    if (subscriptions.contains(CompletionService.AVAILABLE_SUGGESTION_SETS)) {
      includedElementKinds = Set<ElementKind>();
      includedSuggestionRelevanceTags = <IncludedSuggestionRelevanceTag>[];
    }

    // Compute suggestions in the background
    computeSuggestions(
      completionRequest,
      params,
      includedElementKinds,
      includedSuggestionRelevanceTags,
    ).then((CompletionResult result) {
      List<IncludedSuggestionSet> includedSuggestionSets;
      if (includedElementKinds != null && resolvedUnit != null) {
        includedSuggestionSets = computeIncludedSetList(
          server.declarationsTracker,
          resolvedUnit,
        );
      } else {
        includedSuggestionSets = [];
      }

      const SEND_NOTIFICATION_TAG = 'send notification';
      performance.logStartTime(SEND_NOTIFICATION_TAG);
      sendCompletionNotification(
        completionId,
        result.replacementOffset,
        result.replacementLength,
        result.suggestions,
        includedSuggestionSets,
        includedElementKinds?.toList(),
        includedSuggestionRelevanceTags,
      );
      performance.logElapseTime(SEND_NOTIFICATION_TAG);

      performance.notificationCount = 1;
      performance.logFirstNotificationComplete('notification 1 complete');
      performance.suggestionCountFirst = result.suggestions.length;
      performance.suggestionCountLast = result.suggestions.length;
      performance.complete();
    }).whenComplete(() {
      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,
    List<IncludedSuggestionSet> includedSuggestionSets,
    List<ElementKind> includedElementKinds,
    List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags,
  ) {
    server.sendNotification(
      new CompletionResultsParams(
        completionId,
        replacementOffset,
        replacementLength,
        results,
        true,
        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)) {
      server.createDeclarationsTracker((change) {
        server.sendNotification(
          createCompletionAvailableSuggestionsNotification(change),
        );
      });
    } else {
      server.disposeDeclarationsTracker();
    }

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