// 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.

library domain.completion;

import 'dart:async';

import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/constants.dart';
import 'package:analysis_server/src/context_manager.dart';
import 'package:analysis_server/src/provisional/completion/completion_core.dart'
    show CompletionRequest, CompletionResult;
import 'package:analysis_server/src/services/completion/completion_core.dart';
import 'package:analysis_server/src/services/completion/completion_manager.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';

export 'package:analysis_server/src/services/completion/completion_manager.dart'
    show CompletionPerformance, CompletionRequest, OperationPerformance;

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

  /**
   * The analysis server that is using this handler to process requests.
   */
  final AnalysisServer server;

  /**
   * The [SearchEngine] for this server.
   */
  SearchEngine searchEngine;

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

  /**
   * The completion manager for most recent [Source] and [AnalysisContext],
   * or `null` if none.
   */
  CompletionManager _manager;

  /**
   * The subscription for the cached context's source change stream.
   */
  StreamSubscription<SourcesChangedEvent> _sourcesChangedSubscription;

  /**
   * 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 List<CompletionPerformance> performanceList =
      new List<CompletionPerformance>();

  /**
   * Performance for the last priority change event.
   */
  CompletionPerformance computeCachePerformance;

  /**
   * Initialize a new request handler for the given [server].
   */
  CompletionDomainHandler(this.server) {
    server.onContextsChanged.listen(contextsChanged);
    server.onPriorityChange.listen(priorityChanged);
    searchEngine = server.searchEngine;
  }

  /**
   * Return the completion manager for most recent [Source] and [AnalysisContext],
   * or `null` if none.
   */
  CompletionManager get manager => _manager;

  /**
   * Return the [CompletionManager] for the given [context] and [source],
   * creating a new manager or returning an existing manager as necessary.
   */
  CompletionManager completionManagerFor(
      AnalysisContext context, Source source) {
    if (_manager != null) {
      if (_manager.context == context && _manager.source == source) {
        return _manager;
      }
      _discardManager();
    }
    _manager = createCompletionManager(server, context, source);
    if (context != null) {
      _sourcesChangedSubscription =
          context.onSourcesChanged.listen(sourcesChanged);
    }
    return _manager;
  }

  /**
   * If the context associated with the cache has changed or been removed
   * then discard the cache.
   */
  void contextsChanged(ContextsChangedEvent event) {
    if (_manager != null) {
      AnalysisContext context = _manager.context;
      if (event.changed.contains(context) || event.removed.contains(context)) {
        _discardManager();
      }
    }
  }

  CompletionManager createCompletionManager(
      AnalysisServer server, AnalysisContext context, Source source) {
    return new CompletionManager.create(context, source, server.searchEngine,
        server.serverPlugin.completionContributors);
  }

  @override
  Response handleRequest(Request request) {
    if (searchEngine == null) {
      return new Response.noIndexGenerated(request);
    }
    return runZoned(() {
      try {
        String requestName = request.method;
        if (requestName == COMPLETION_GET_SUGGESTIONS) {
          return processRequest(request);
        }
      } on RequestFailure catch (exception) {
        return exception.response;
      }
      return null;
    }, onError: (exception, stackTrace) {
      server.sendServerErrorNotification(
          'Failed to handle completion domain request: ${request.toJson()}',
          exception,
          stackTrace);
    });
  }

  /**
   * If the set the priority files has changed, then pre-cache completion
   * information related to the first priority file.
   */
  void priorityChanged(PriorityChangeEvent event) {
    Source source = event.firstSource;
    CompletionPerformance performance = new CompletionPerformance();
    computeCachePerformance = performance;
    if (source == null) {
      performance.complete('priorityChanged caching: no source');
      return;
    }
    performance.source = source;
    AnalysisContext context = server.getAnalysisContextForSource(source);
    if (context != null) {
      String computeTag = 'computeCache';
      performance.logStartTime(computeTag);
      CompletionManager manager = completionManagerFor(context, source);
      manager.computeCache().catchError((_) => false).then((bool success) {
        performance.logElapseTime(computeTag);
        performance.complete('priorityChanged caching: $success');
      });
    }
  }

  /**
   * Process a `completion.getSuggestions` request.
   */
  Response processRequest(Request request, [CompletionManager manager]) {
    performance = new CompletionPerformance();
    // extract params
    CompletionGetSuggestionsParams params =
        new CompletionGetSuggestionsParams.fromRequest(request);
    // schedule completion analysis
    String completionId = (_nextCompletionId++).toString();
    ContextSourcePair contextSource = server.getContextSourcePair(params.file);
    AnalysisContext context = contextSource.context;
    Source source = contextSource.source;
    if (context == null || !context.exists(source)) {
      return new Response.unknownSource(request);
    }
    recordRequest(performance, context, source, params.offset);
    if (manager == null) {
      manager = completionManagerFor(context, source);
    }
    CompletionRequest completionRequest = new CompletionRequestImpl(context,
        server.resourceProvider, server.searchEngine, source, params.offset);
    int notificationCount = 0;
    manager.results(completionRequest).listen((CompletionResult result) {
      ++notificationCount;
      bool isLast = result is CompletionResultImpl ? result.isLast : true;
      performance.logElapseTime("notification $notificationCount send", () {
        sendCompletionNotification(completionId, result.replacementOffset,
            result.replacementLength, result.suggestions, isLast);
      });
      if (notificationCount == 1) {
        performance.logFirstNotificationComplete('notification 1 complete');
        performance.suggestionCountFirst = result.suggestions.length;
      }
      if (isLast) {
        performance.notificationCount = notificationCount;
        performance.suggestionCountLast = result.suggestions.length;
        performance.complete();
      }
    });
    // initial response without results
    return new CompletionGetSuggestionsResult(completionId)
        .toResponse(request.id);
  }

  /**
   * If tracking code completion performance over time, then
   * record addition information about the request in the performance record.
   */
  void recordRequest(CompletionPerformance performance, AnalysisContext context,
      Source source, int offset) {
    performance.source = source;
    if (performanceListMaxLength == 0 || context == null || source == null) {
      return;
    }
    TimestampedData<String> data = context.getContents(source);
    if (data == null) {
      return;
    }
    performance.setContentsAndOffset(data.data, offset);
    while (performanceList.length >= performanceListMaxLength) {
      performanceList.removeAt(0);
    }
    performanceList.add(performance);
  }

  /**
   * Send completion notification results.
   */
  void sendCompletionNotification(
      String completionId,
      int replacementOffset,
      int replacementLength,
      Iterable<CompletionSuggestion> results,
      bool isLast) {
    server.sendNotification(new CompletionResultsParams(
            completionId, replacementOffset, replacementLength, results, isLast)
        .toNotification());
  }

  /**
   * Discard the cache if a source other than the source referenced by
   * the cache changes or if any source is added, removed, or deleted.
   */
  void sourcesChanged(SourcesChangedEvent event) {
    bool shouldDiscardManager(SourcesChangedEvent event) {
      if (_manager == null) {
        return false;
      }
      if (event.wereSourcesAdded || event.wereSourcesRemovedOrDeleted) {
        return true;
      }
      var changedSources = event.changedSources;
      return changedSources.length > 2 ||
          (changedSources.length == 1 &&
              !changedSources.contains(_manager.source));
    }

    if (shouldDiscardManager(event)) {
      _discardManager();
    }
  }

  /**
   * Discard the sourcesChanged subscription if any
   */
  void _discardManager() {
    if (_sourcesChangedSubscription != null) {
      _sourcesChangedSubscription.cancel();
      _sourcesChangedSubscription = null;
    }
    if (_manager != null) {
      _manager.dispose();
      _manager = null;
    }
  }
}
