// 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 services.completion.dart;

import 'dart:async';

import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:analysis_server/src/provisional/completion/completion_core.dart'
    show AnalysisRequest, CompletionContributor, CompletionRequest;
import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
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/completion/dart/common_usage_sorter.dart';
import 'package:analysis_server/src/services/completion/dart/contribution_sorter.dart';
import 'package:analysis_server/src/services/completion/dart_completion_cache.dart';
import 'package:analysis_server/src/services/completion/imported_reference_contributor.dart';
import 'package:analysis_server/src/services/completion/local_reference_contributor.dart';
import 'package:analysis_server/src/services/completion/optype.dart';
import 'package:analysis_server/src/services/completion/prefixed_element_contributor.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart' hide AnalysisContextImpl;
import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';

export 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart'
    show
        DART_RELEVANCE_COMMON_USAGE,
        DART_RELEVANCE_DEFAULT,
        DART_RELEVANCE_HIGH,
        DART_RELEVANCE_INHERITED_ACCESSOR,
        DART_RELEVANCE_INHERITED_FIELD,
        DART_RELEVANCE_INHERITED_METHOD,
        DART_RELEVANCE_KEYWORD,
        DART_RELEVANCE_LOCAL_ACCESSOR,
        DART_RELEVANCE_LOCAL_FIELD,
        DART_RELEVANCE_LOCAL_FUNCTION,
        DART_RELEVANCE_LOCAL_METHOD,
        DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE,
        DART_RELEVANCE_LOCAL_VARIABLE,
        DART_RELEVANCE_LOW,
        DART_RELEVANCE_NAMED_PARAMETER,
        DART_RELEVANCE_PARAMETER;

/**
 * The base class for contributing code completion suggestions.
 */
abstract class DartCompletionContributor {
  /**
   * Computes the initial set of [CompletionSuggestion]s based on
   * the given completion context. The compilation unit and completion node
   * in the given completion context may not be resolved.
   * This method should execute quickly and not block waiting for any analysis.
   * Returns `true` if the contributor's work is complete
   * or `false` if [computeFull] should be called to complete the work.
   */
  bool computeFast(DartCompletionRequest request);

  /**
   * Computes the complete set of [CompletionSuggestion]s based on
   * the given completion context.  The compilation unit and completion node
   * in the given completion context are resolved.
   * Returns `true` if the receiver modified the list of suggestions.
   */
  Future<bool> computeFull(DartCompletionRequest request);
}

/**
 * Manages code completion for a given Dart file completion request.
 */
class DartCompletionManager extends CompletionManager {
  /**
   * The [defaultContributionSorter] is a long-lived object that isn't allowed
   * to maintain state between calls to [ContributionSorter#sort(...)].
   */
  static DartContributionSorter defaultContributionSorter =
      new CommonUsageSorter();

  final SearchEngine searchEngine;
  final DartCompletionCache cache;
  List<DartCompletionContributor> contributors;
  Iterable<CompletionContributor> newContributors;
  DartContributionSorter contributionSorter;

  DartCompletionManager(
      AnalysisContext context, this.searchEngine, Source source, this.cache,
      [this.contributors, this.newContributors, this.contributionSorter])
      : super(context, source) {
    if (contributors == null) {
      contributors = [
        // LocalReferenceContributor before ImportedReferenceContributor
        // because local suggestions take precedence
        // and can hide other suggestions with the same name
        new LocalReferenceContributor(),
        new ImportedReferenceContributor(),
        //new KeywordContributor(),
        //new ArgListContributor(),
        // new CombinatorContributor(),
        new PrefixedElementContributor(),
        //new UriContributor(),
        // TODO(brianwilkerson) Use the completion contributor extension point
        // to add the contributor below (and eventually, all the contributors).
//        new NewCompletionWrapper(new InheritedContributor())
      ];
    }
    if (newContributors == null) {
      newContributors = <CompletionContributor>[];
    }
    if (contributionSorter == null) {
      contributionSorter = defaultContributionSorter;
    }
  }

  /**
   * Create a new initialized Dart source completion manager
   */
  factory DartCompletionManager.create(
      AnalysisContext context,
      SearchEngine searchEngine,
      Source source,
      Iterable<CompletionContributor> newContributors) {
    return new DartCompletionManager(context, searchEngine, source,
        new DartCompletionCache(context, source), null, newContributors);
  }

  @override
  Future<bool> computeCache() {
    return waitForAnalysis().then((CompilationUnit unit) {
      if (unit != null && !cache.isImportInfoCached(unit)) {
        return cache.computeImportInfo(unit, searchEngine, true);
      } else {
        return new Future.value(false);
      }
    });
  }

  /**
   * Compute suggestions based upon cached information only
   * then send an initial response to the client.
   * Return a list of contributors for which [computeFull] should be called
   */
  List<DartCompletionContributor> computeFast(
      DartCompletionRequest request, CompletionPerformance performance) {
    return performance.logElapseTime('computeFast', () {
      CompilationUnit unit = context.parseCompilationUnit(source);
      request.unit = unit;
      request.target = new CompletionTarget.forOffset(unit, request.offset);
      if (request.offset < 0 || request.offset > unit.end) {
        request.replacementOffset = request.offset;
        request.replacementLength = 0;
        sendResults(request, true);
        return [];
      }

      ReplacementRange range =
          new ReplacementRange.compute(request.offset, request.target);
      request.replacementOffset = range.offset;
      request.replacementLength = range.length;

      List<DartCompletionContributor> todo = new List.from(contributors);
      todo.removeWhere((DartCompletionContributor c) {
        return performance.logElapseTime('computeFast ${c.runtimeType}', () {
          return c.computeFast(request);
        });
      });
      return todo;
    });
  }

  /**
   * If there is remaining work to be done, then wait for the unit to be
   * resolved and request that each remaining contributor finish their work.
   * Return a [Future] that completes when the last notification has been sent.
   */
  Future computeFull(
      DartCompletionRequest request,
      CompletionPerformance performance,
      List<DartCompletionContributor> todo) async {
    // Compute suggestions using the new API
    performance.logStartTime('computeSuggestions');
    for (CompletionContributor contributor in newContributors) {
      String contributorTag = 'computeSuggestions - ${contributor.runtimeType}';
      performance.logStartTime(contributorTag);
      List<CompletionSuggestion> newSuggestions =
          await contributor.computeSuggestions(request);
      for (CompletionSuggestion suggestion in newSuggestions) {
        request.addSuggestion(suggestion);
      }
      performance.logElapseTime(contributorTag);
    }
    performance.logElapseTime('computeSuggestions');
    performance.logStartTime('waitForAnalysis');

    if (todo.isEmpty) {
      // TODO(danrubel) current sorter requires no additional analysis,
      // but need to handle the returned future the same way that futures
      // returned from contributors are handled once this method is refactored
      // to be async.
      /* await */ contributionSorter.sort(request, request.suggestions);
      // TODO (danrubel) if request is obsolete
      // (processAnalysisRequest returns false)
      // then send empty results
      sendResults(request, true);
    }

    // Compute the other suggestions
    return waitForAnalysis().then((CompilationUnit unit) {
      if (controller.isClosed) {
        return;
      }
      performance.logElapseTime('waitForAnalysis');
      if (unit == null) {
        sendResults(request, true);
        return;
      }
      performance.logElapseTime('computeFull', () {
        request.unit = unit;
        // TODO(paulberry): Do we need to invoke _ReplacementOffsetBuilder
        // again?
        request.target = new CompletionTarget.forOffset(unit, request.offset);
        int count = todo.length;
        todo.forEach((DartCompletionContributor c) {
          String name = c.runtimeType.toString();
          String completeTag = 'computeFull $name complete';
          performance.logStartTime(completeTag);
          performance.logElapseTime('computeFull $name', () {
            c.computeFull(request).then((bool changed) {
              performance.logElapseTime(completeTag);
              bool last = --count == 0;
              if (changed || last) {
                // TODO(danrubel) current sorter requires no additional analysis,
                // but need to handle the returned future the same way that futures
                // returned from contributors are handled once this method is refactored
                // to be async.
                /* await */ contributionSorter.sort(
                    request, request.suggestions);
                // TODO (danrubel) if request is obsolete
                // (processAnalysisRequest returns false)
                // then send empty results
                sendResults(request, last);
              }
            });
          });
        });
      });
    });
  }

  @override
  void computeSuggestions(CompletionRequest completionRequest) {
    DartCompletionRequest request =
        new DartCompletionRequest.from(completionRequest, cache);
    CompletionPerformance performance = new CompletionPerformance();
    performance.logElapseTime('compute', () {
      List<DartCompletionContributor> todo = computeFast(request, performance);
      computeFull(request, performance, todo);
    });
  }

  /**
   * Send the current list of suggestions to the client.
   */
  void sendResults(DartCompletionRequest request, bool last) {
    if (controller == null || controller.isClosed) {
      return;
    }
    controller.add(new CompletionResultImpl(request.replacementOffset,
        request.replacementLength, request.suggestions, last));
    if (last) {
      controller.close();
    }
  }

  /**
   * Return a future that either (a) completes with the resolved compilation
   * unit when analysis is complete, or (b) completes with null if the
   * compilation unit is never going to be resolved.
   */
  Future<CompilationUnit> waitForAnalysis() {
    List<Source> libraries = context.getLibrariesContaining(source);
    assert(libraries != null);
    if (libraries.length == 0) {
      return new Future.value(null);
    }
    Source libSource = libraries[0];
    assert(libSource != null);
    return context
        .computeResolvedCompilationUnitAsync(source, libSource)
        .catchError((_) {
      // This source file is not scheduled for analysis, so a resolved
      // compilation unit is never going to get computed.
      return null;
    }, test: (e) => e is AnalysisNotScheduledError);
  }
}

/**
 * The context in which the completion is requested.
 */
class DartCompletionRequest extends CompletionRequestImpl {
  /**
   * Cached information from a prior code completion operation.
   */
  final DartCompletionCache cache;

  /**
   * The compilation unit in which the completion was requested. This unit
   * may or may not be resolved when [DartCompletionContributor.computeFast]
   * is called but is resolved when [DartCompletionContributor.computeFull].
   */
  CompilationUnit unit;

  /**
   * The completion target.  This determines what part of the parse tree
   * will receive the newly inserted text.
   */
  CompletionTarget target;

  /**
   * Information about the types of suggestions that should be included.
   */
  OpType _optype;

  /**
   * 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.
   */
  int replacementOffset;

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

  /**
   * The list of suggestions to be sent to the client.
   */
  final List<CompletionSuggestion> _suggestions = <CompletionSuggestion>[];

  /**
   * The set of completions used to prevent duplicates
   */
  final Set<String> _completions = new Set<String>();

  DartCompletionRequest(
      AnalysisContext context,
      ResourceProvider resourceProvider,
      SearchEngine searchEngine,
      Source source,
      int offset,
      this.cache)
      : super(context, resourceProvider, searchEngine, source, offset);

  factory DartCompletionRequest.from(
          CompletionRequestImpl request, DartCompletionCache cache) =>
      new DartCompletionRequest(request.context, request.resourceProvider,
          request.searchEngine, request.source, request.offset, cache);

  /**
   * Return the original text from the [replacementOffset] to the [offset]
   * that can be used to filter the suggestions on the server side.
   */
  String get filterText {
    return context
        .getContents(source)
        .data
        .substring(replacementOffset, offset);
  }

  /**
   * Information about the types of suggestions that should be included.
   * The [target] must be set first.
   */
  OpType get optype {
    if (_optype == null) {
      _optype = new OpType.forCompletion(target, offset);
    }
    return _optype;
  }

  /**
   * The list of suggestions to be sent to the client.
   */
  Iterable<CompletionSuggestion> get suggestions => _suggestions;

  /**
   * Add the given suggestion to the list that is returned to the client as long
   * as a suggestion with an identical completion has not already been added.
   */
  void addSuggestion(CompletionSuggestion suggestion) {
    if (_completions.add(suggestion.completion)) {
      _suggestions.add(suggestion);
    }
  }

  /**
   * Convert all [CompletionSuggestionKind.INVOCATION] suggestions
   * to [CompletionSuggestionKind.IDENTIFIER] suggestions.
   */
  void convertInvocationsToIdentifiers() {
    for (int index = _suggestions.length - 1; index >= 0; --index) {
      CompletionSuggestion suggestion = _suggestions[index];
      if (suggestion.kind == CompletionSuggestionKind.INVOCATION) {
        // Create a copy rather than just modifying the existing suggestion
        // because [DartCompletionCache] may be caching that suggestion
        // for future completion requests
        _suggestions[index] = new CompletionSuggestion(
            CompletionSuggestionKind.IDENTIFIER,
            suggestion.relevance,
            suggestion.completion,
            suggestion.selectionOffset,
            suggestion.selectionLength,
            suggestion.isDeprecated,
            suggestion.isPotential,
            declaringType: suggestion.declaringType,
            parameterNames: suggestion.parameterNames,
            parameterTypes: suggestion.parameterTypes,
            requiredParameterCount: suggestion.requiredParameterCount,
            hasNamedParameters: suggestion.hasNamedParameters,
            returnType: suggestion.returnType,
            element: suggestion.element);
      }
    }
  }
}

/**
 * Utility class for computing the code completion replacement range
 */
class ReplacementRange {
  int offset;
  int length;

  ReplacementRange(this.offset, this.length);

  factory ReplacementRange.compute(int requestOffset, CompletionTarget target) {
    bool isKeywordOrIdentifier(Token token) =>
        token.type == TokenType.KEYWORD || token.type == TokenType.IDENTIFIER;

    //TODO(danrubel) Ideally this needs to be pushed down into the contributors
    // but that implies that each suggestion can have a different
    // replacement offsent/length which would mean an API change

    var entity = target.entity;
    Token token = entity is AstNode ? entity.beginToken : entity;
    if (token != null && requestOffset < token.offset) {
      token = token.previous;
    }
    if (token != null) {
      if (requestOffset == token.offset && !isKeywordOrIdentifier(token)) {
        // If the insertion point is at the beginning of the current token
        // and the current token is not an identifier
        // then check the previous token to see if it should be replaced
        token = token.previous;
      }
      if (token != null && isKeywordOrIdentifier(token)) {
        if (token.offset <= requestOffset && requestOffset <= token.end) {
          // Replacement range for typical identifier completion
          return new ReplacementRange(token.offset, token.length);
        }
      }
      if (token is StringToken) {
        SimpleStringLiteral uri = new SimpleStringLiteral(token, token.lexeme);
        Token previous = token.previous;
        if (previous is KeywordToken) {
          Keyword keyword = previous.keyword;
          if (keyword == Keyword.IMPORT ||
              keyword == Keyword.EXPORT ||
              keyword == Keyword.PART) {
            int start = uri.contentsOffset;
            var end = uri.contentsEnd;
            if (start <= requestOffset && requestOffset <= end) {
              // Replacement range for import URI
              return new ReplacementRange(start, end - start);
            }
          }
        }
      }
    }
    return new ReplacementRange(requestOffset, 0);
  }
}
