// Copyright (c) 2015, 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/src/protocol_server.dart';
import 'package:analysis_server/src/provisional/completion/completion_core.dart'
    show AbortCompletion, CompletionContributor, CompletionRequest;
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.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/arglist_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/combinator_contributor.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/field_formal_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/imported_reference_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/inherited_reference_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/keyword_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/label_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/library_member_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/library_prefix_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/local_constructor_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/local_reference_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/named_constructor_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/override_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/static_member_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/type_member_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/uri_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/variable_name_contributor.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
import 'package:analyzer_plugin/src/utilities/completion/optype.dart';

/**
 * [DartCompletionManager] determines if a completion request is Dart specific
 * and forwards those requests to all [DartCompletionContributor]s.
 */
class DartCompletionManager implements CompletionContributor {
  /**
   * The [contributionSorter] is a long-lived object that isn't allowed
   * to maintain state between calls to [DartContributionSorter#sort(...)].
   */
  static DartContributionSorter contributionSorter = new CommonUsageSorter();

  /// If not `null`, then instead of using [ImportedReferenceContributor],
  /// fill this set with kinds of elements that are applicable at the
  /// completion location, so should be suggested from available suggestion
  /// sets.
  final Set<protocol.ElementKind> includedElementKinds;

  /// If [includedElementKinds] is not null, must be also not `null`, and
  /// will be filled with tags for suggestions that should be given higher
  /// relevance than other included suggestions.
  final List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags;

  DartCompletionManager({
    this.includedElementKinds,
    this.includedSuggestionRelevanceTags,
  });

  @override
  Future<List<CompletionSuggestion>> computeSuggestions(
      CompletionRequest request) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    request.checkAborted();
    if (!AnalysisEngine.isDartFileName(request.result.path)) {
      return const <CompletionSuggestion>[];
    }

    CompletionPerformance performance =
        (request as CompletionRequestImpl).performance;
    DartCompletionRequestImpl dartRequest =
        await DartCompletionRequestImpl.from(request);

    // Don't suggest in comments.
    if (dartRequest.target.isCommentText) {
      return const <CompletionSuggestion>[];
    }

    SourceRange range =
        dartRequest.target.computeReplacementRange(dartRequest.offset);
    (request as CompletionRequestImpl)
      ..replacementOffset = range.offset
      ..replacementLength = range.length;

    // Request Dart specific completions from each contributor
    var suggestionMap = <String, CompletionSuggestion>{};
    var constructorMap = <String, List<String>>{};
    List<DartCompletionContributor> contributors = <DartCompletionContributor>[
      new ArgListContributor(),
      new CombinatorContributor(),
      new FieldFormalContributor(),
      new InheritedReferenceContributor(),
      new KeywordContributor(),
      new LabelContributor(),
      new LibraryMemberContributor(),
      new LibraryPrefixContributor(),
      new LocalConstructorContributor(),
      new LocalLibraryContributor(),
      new LocalReferenceContributor(),
      new NamedConstructorContributor(),
      new OverrideContributor(),
      new StaticMemberContributor(),
      new TypeMemberContributor(),
      new UriContributor(),
      new VariableNameContributor()
    ];

    if (includedElementKinds != null) {
      _addIncludedElementKinds(dartRequest);
      _addIncludedSuggestionRelevanceTags(dartRequest);
    } else {
      contributors.add(new ImportedReferenceContributor());
    }

    try {
      for (DartCompletionContributor contributor in contributors) {
        String contributorTag =
            'DartCompletionManager - ${contributor.runtimeType}';
        performance.logStartTime(contributorTag);
        List<CompletionSuggestion> contributorSuggestions =
            await contributor.computeSuggestions(dartRequest);
        performance.logElapseTime(contributorTag);
        request.checkAborted();

        for (CompletionSuggestion newSuggestion in contributorSuggestions) {
          String key = newSuggestion.completion;

          // Append parenthesis for constructors to disambiguate from classes.
          if (_isConstructor(newSuggestion)) {
            key += '()';
            String className = _getConstructorClassName(newSuggestion);
            _ensureList(constructorMap, className).add(key);
          }

          // Local declarations hide both the class and its constructors.
          if (!_isClass(newSuggestion)) {
            List<String> constructorKeys = constructorMap[key];
            constructorKeys?.forEach(suggestionMap.remove);
          }

          CompletionSuggestion oldSuggestion = suggestionMap[key];
          if (oldSuggestion == null ||
              oldSuggestion.relevance < newSuggestion.relevance) {
            suggestionMap[key] = newSuggestion;
          }
        }
      }
    } on InconsistentAnalysisException {
      // The state of the code being analyzed has changed, so results are likely
      // to be inconsistent. Just abort the operation.
      throw new AbortCompletion();
    }

    // Adjust suggestion relevance before returning
    List<CompletionSuggestion> suggestions = suggestionMap.values.toList();
    const SORT_TAG = 'DartCompletionManager - sort';
    performance.logStartTime(SORT_TAG);
    await contributionSorter.sort(dartRequest, suggestions);
    performance.logElapseTime(SORT_TAG);
    request.checkAborted();
    return suggestions;
  }

  void _addIncludedElementKinds(DartCompletionRequestImpl request) {
    var opType = request.opType;

    if (!opType.includeIdentifiers) return;

    var kinds = includedElementKinds;
    if (kinds != null) {
      if (opType.includeConstructorSuggestions) {
        kinds.add(protocol.ElementKind.CONSTRUCTOR);
      }
      if (opType.includeTypeNameSuggestions) {
        kinds.add(protocol.ElementKind.CLASS);
        kinds.add(protocol.ElementKind.CLASS_TYPE_ALIAS);
        kinds.add(protocol.ElementKind.ENUM);
        kinds.add(protocol.ElementKind.FUNCTION_TYPE_ALIAS);
        kinds.add(protocol.ElementKind.MIXIN);
      }
      if (opType.includeReturnValueSuggestions) {
        kinds.add(protocol.ElementKind.CONSTRUCTOR);
        kinds.add(protocol.ElementKind.ENUM_CONSTANT);
        kinds.add(protocol.ElementKind.FUNCTION);
        kinds.add(protocol.ElementKind.TOP_LEVEL_VARIABLE);
      }
    }
  }

  void _addIncludedSuggestionRelevanceTags(DartCompletionRequestImpl request) {
    var target = request.target;

    void addTypeTag(DartType type) {
      if (type is InterfaceType) {
        var element = type.element;
        var tag = '${element.librarySource.uri}::${element.name}';
        if (element.isEnum) {
          includedSuggestionRelevanceTags.add(
            IncludedSuggestionRelevanceTag(
              tag,
              DART_RELEVANCE_BOOST_AVAILABLE_ENUM,
            ),
          );
        } else {
          includedSuggestionRelevanceTags.add(
            IncludedSuggestionRelevanceTag(
              tag,
              DART_RELEVANCE_BOOST_AVAILABLE_DECLARATION,
            ),
          );
        }
      }
    }

    var parameter = target.parameterElement;
    if (parameter != null) {
      addTypeTag(parameter.type);
    }

    var containingNode = target.containingNode;

    if (containingNode is AssignmentExpression &&
        containingNode.operator.type == TokenType.EQ &&
        target.offset >= containingNode.operator.end) {
      addTypeTag(containingNode.leftHandSide.staticType);
    }

    if (containingNode is ListLiteral &&
        target.offset >= containingNode.leftBracket.end &&
        target.offset <= containingNode.rightBracket.offset) {
      var type = containingNode.staticType;
      if (type is InterfaceType) {
        var typeArguments = type.typeArguments;
        if (typeArguments.isNotEmpty) {
          addTypeTag(typeArguments[0]);
        }
      }
    }
  }

  static List<String> _ensureList(Map<String, List<String>> map, String key) {
    List<String> list = map[key];
    if (list == null) {
      list = <String>[];
      map[key] = list;
    }
    return list;
  }

  static String _getConstructorClassName(CompletionSuggestion suggestion) {
    String completion = suggestion.completion;
    int dotIndex = completion.indexOf('.');
    if (dotIndex != -1) {
      return completion.substring(0, dotIndex);
    } else {
      return completion;
    }
  }

  static bool _isClass(CompletionSuggestion suggestion) {
    return suggestion.element?.kind == protocol.ElementKind.CLASS;
  }

  static bool _isConstructor(CompletionSuggestion suggestion) {
    return suggestion.element?.kind == protocol.ElementKind.CONSTRUCTOR;
  }
}

/**
 * The information about a requested list of completions within a Dart file.
 */
class DartCompletionRequestImpl implements DartCompletionRequest {
  @override
  final ResolvedUnitResult result;

  @override
  final ResourceProvider resourceProvider;

  @override
  final InterfaceType objectType;

  @override
  final Source source;

  @override
  final int offset;

  @override
  Expression dotTarget;

  @override
  final Source librarySource;

  @override
  CompletionTarget target;

  OpType _opType;

  final CompletionRequest _originalRequest;

  final CompletionPerformance performance;

  DartCompletionRequestImpl._(
      this.result,
      this.resourceProvider,
      this.objectType,
      this.librarySource,
      this.source,
      this.offset,
      CompilationUnit unit,
      this._originalRequest,
      this.performance) {
    _updateTargets(unit);
  }

  @override
  List<String> get enabledExperiments =>
      result.session.analysisContext.analysisOptions.enabledExperiments;

  @override
  bool get includeIdentifiers {
    return opType.includeIdentifiers;
  }

  @override
  LibraryElement get libraryElement {
    //TODO(danrubel) build the library element rather than all the declarations
    CompilationUnit unit = target.unit;
    if (unit != null) {
      CompilationUnitElement elem = unit.declaredElement;
      if (elem != null) {
        return elem.library;
      }
    }
    return null;
  }

  OpType get opType {
    if (_opType == null) {
      _opType = new OpType.forCompletion(target, offset);
    }
    return _opType;
  }

  @override
  String get sourceContents => result.content;

  @override
  SourceFactory get sourceFactory {
    DriverBasedAnalysisContext context = result.session.analysisContext;
    return context.driver.sourceFactory;
  }

  /**
   * Throw [AbortCompletion] if the completion request has been aborted.
   */
  void checkAborted() {
    _originalRequest.checkAborted();
  }

  /**
   * Update the completion [target] and [dotTarget] based on the given [unit].
   */
  void _updateTargets(CompilationUnit unit) {
    _opType = null;
    dotTarget = null;
    target = new CompletionTarget.forOffset(unit, offset);
    AstNode node = target.containingNode;
    if (node is MethodInvocation) {
      if (identical(node.methodName, target.entity)) {
        dotTarget = node.realTarget;
      } else if (node.isCascaded && node.operator.offset + 1 == target.offset) {
        dotTarget = node.realTarget;
      }
    }
    if (node is PropertyAccess) {
      if (identical(node.propertyName, target.entity)) {
        dotTarget = node.realTarget;
      } else if (node.isCascaded && node.operator.offset + 1 == target.offset) {
        dotTarget = node.realTarget;
      }
    }
    if (node is PrefixedIdentifier) {
      if (identical(node.identifier, target.entity)) {
        dotTarget = node.prefix;
      }
    }
  }

  /**
   * Return a [Future] that completes with a newly created completion request
   * based on the given [request]. This method will throw [AbortCompletion]
   * if the completion request has been aborted.
   */
  static Future<DartCompletionRequest> from(CompletionRequest request) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    request.checkAborted();
    CompletionPerformance performance =
        (request as CompletionRequestImpl).performance;
    const BUILD_REQUEST_TAG = 'build DartCompletionRequest';
    performance.logStartTime(BUILD_REQUEST_TAG);

    CompilationUnit unit = request.result.unit;
    Source libSource = unit.declaredElement.library.source;
    InterfaceType objectType = request.result.typeProvider.objectType;

    DartCompletionRequestImpl dartRequest = new DartCompletionRequestImpl._(
        request.result,
        request.resourceProvider,
        objectType,
        libSource,
        request.source,
        request.offset,
        unit,
        request,
        performance);

    performance.logElapseTime(BUILD_REQUEST_TAG);
    return dartRequest;
  }
}
