// 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/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: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;

/**
 * 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 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;

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

      CompletionContributor contributor = new DartCompletionManager();
      String contributorTag = 'computeSuggestions - ${contributor
          .runtimeType}';
      performance.logStartTime(contributorTag);
      try {
        suggestions.addAll(await contributor.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);
  }

  @override
  Response handleRequest(Request request) {
    return runZoned(() {
      String requestName = request.method;
      if (requestName == COMPLETION_REQUEST_GET_SUGGESTIONS) {
        processRequest(request);
        return Response.DELAYED_RESPONSE;
      }
      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.getSuggestions` request.
   */
  Future<Null> 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 filePath = params.file;
    int offset = params.offset;

    AnalysisResult result = await server.getAnalysisResult(filePath);

    if (result == null || !result.exists) {
      if (server.onNoAnalysisCompletion != null) {
        String completionId = (_nextCompletionId++).toString();
        await server.onNoAnalysisCompletion(
            request, this, params, performance, completionId);
        return;
      }
    } else {
      if (offset < 0 || offset > result.content.length) {
        server.sendResponse(new Response.invalidParameter(
            request,
            'params.offset',
            'Expected offset between 0 and source length inclusive,'
            ' but found $offset'));
        return;
      }

      recordRequest(performance, filePath, result.content, offset);
    }
    CompletionRequestImpl completionRequest =
        new CompletionRequestImpl(result, offset, performance);

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

    setNewRequest(completionRequest);

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

    // Compute suggestions in the background
    computeSuggestions(completionRequest, params)
        .then((CompletionResult result) {
      const SEND_NOTIFICATION_TAG = 'send notification';
      performance.logStartTime(SEND_NOTIFICATION_TAG);
      sendCompletionNotification(completionId, result.replacementOffset,
          result.replacementLength, result.suggestions);
      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) {
    server.sendNotification(new CompletionResultsParams(
            completionId, replacementOffset, replacementLength, results, true)
        .toNotification());
  }

  void setNewRequest(CompletionRequest completionRequest) {
    _abortCurrentRequest();
    _currentRequest = completionRequest;
  }

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