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

library services.completion.dart.manager;

import 'dart:async';

import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:analysis_server/src/provisional/completion/completion_core.dart'
    show CompletionContributor, CompletionRequest;
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_plugin.dart';
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_performance.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/optype.dart';
import 'package:analysis_server/src/services/search/search_engine.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/exception/exception.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/context/context.dart' show AnalysisFutureHelper;
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/task/dart.dart';
import 'package:analyzer/task/model.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();

  @override
  Future<List<CompletionSuggestion>> computeSuggestions(
      CompletionRequest request) async {
    request.checkAborted();
    if (!AnalysisEngine.isDartFileName(request.source.shortName)) {
      return EMPTY_LIST;
    }

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

    // Don't suggest in comments.
    if (dartRequest.target.isCommentText) {
      return EMPTY_LIST;
    }

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

    // Request Dart specific completions from each contributor
    Map<String, CompletionSuggestion> suggestionMap =
        <String, CompletionSuggestion>{};
    for (DartCompletionContributor contributor
        in dartCompletionPlugin.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) {
        var oldSuggestion = suggestionMap.putIfAbsent(
            newSuggestion.completion, () => newSuggestion);
        if (newSuggestion != oldSuggestion &&
            newSuggestion.relevance > oldSuggestion.relevance) {
          suggestionMap[newSuggestion.completion] = newSuggestion;
        }
      }
    }

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

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

  @override
  final AnalysisContext context;

  @override
  final Source source;

  @override
  final int offset;

  @override
  Expression dotTarget;

  @override
  Source librarySource;

  @override
  final ResourceProvider resourceProvider;

  @override
  final SearchEngine searchEngine;

  @override
  CompletionTarget target;

  /**
   * The [LibraryElement] representing dart:core
   */
  LibraryElement _coreLib;

  /**
   * The [DartType] for Object in dart:core
   */
  InterfaceType _objectType;

  /**
   * A list of resolved [ImportElement]s for the imported libraries
   * or `null` if not computed.
   */
  List<ImportElement> _resolvedImports;

  /**
   * The resolved [CompilationUnitElement]s comprising the library
   * or `null` if not computed.
   */
  List<CompilationUnitElement> _resolvedUnits;

  OpType _opType;

  final CompletionRequest _originalRequest;

  final CompletionPerformance performance;

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

  @override
  LibraryElement get coreLib {
    if (result != null) {
      AnalysisContext context = result.unit.element.context;
      _coreLib = context.typeProvider.objectType.element.library;
    } else {
      Source coreUri = sourceFactory.forUri('dart:core');
      _coreLib = context.computeLibraryElement(coreUri);
    }
    return _coreLib;
  }

  @override
  bool get includeIdentifiers {
    opType; // <<< ensure _opType is initialized
    return !_opType.isPrefixed &&
        (_opType.includeReturnValueSuggestions ||
            _opType.includeTypeNameSuggestions ||
            _opType.includeVoidReturnSuggestions ||
            _opType.includeConstructorSuggestions);
  }

  @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.element;
      if (elem != null) {
        return elem.library;
      }
    }
    return null;
  }

  @override
  InterfaceType get objectType {
    if (_objectType == null) {
      _objectType = coreLib.getType('Object').type;
    }
    return _objectType;
  }

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

  @override
  String get sourceContents => context.getContents(source)?.data;

  @override
  SourceFactory get sourceFactory {
    return context?.sourceFactory ?? result.sourceFactory;
  }

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

  @override
  Future resolveContainingExpression(AstNode node) async {
    // TODO When an Expression can be resolved instead of just an entire unit,
    // this will be revisited with code searching up the parent until an
    // Expression is found.

    return resolveContainingStatement(node);
  }

  @override
  Future resolveContainingStatement(AstNode node) async {
    // TODO When a Statement can be resolved instead of just an entire unit,
    // this will be revisited with code searching up the parent until a
    // Statement is found.

    checkAborted();

    // Return immediately if the expression has already been resolved
    if (node is Expression && node.propagatedType != null) {
      return;
    }

    // Gracefully degrade if librarySource cannot be determined
    if (librarySource == null) {
      return;
    }

    // Resolve declarations in the target unit
    // TODO(danrubel) resolve the expression or containing method
    // rather than the entire compilation unit
    CompilationUnit resolvedUnit;
    if (result != null) {
      resolvedUnit = result.unit;
    } else {
      resolvedUnit = await _computeAsync(
          this,
          new LibrarySpecificUnit(librarySource, source),
          RESOLVED_UNIT,
          performance,
          'resolve expression');
    }

    // TODO(danrubel) determine if the underlying source has been modified
    // in a way that invalidates the completion request
    // and return null

    // Gracefully degrade if unit cannot be resolved
    if (resolvedUnit == null) {
      return;
    }

    // Recompute the target for the newly resolved unit
    _updateTargets(resolvedUnit);
  }

  @override
  Future<List<ImportElement>> resolveImports() async {
    checkAborted();
    if (_resolvedImports != null) {
      return _resolvedImports;
    }
    LibraryElement libElem = libraryElement;
    if (libElem == null) {
      return null;
    }
    _resolvedImports = <ImportElement>[];
    for (ImportElement importElem in libElem.imports) {
      if (importElem.importedLibrary?.exportNamespace == null) {
        await _computeAsync(this, importElem.importedLibrary.source,
            LIBRARY_ELEMENT4, performance, 'resolve imported library');
        checkAborted();
      }
      _resolvedImports.add(importElem);
    }
    return _resolvedImports;
  }

  @override
  Future<List<CompilationUnitElement>> resolveUnits() async {
    checkAborted();
    if (_resolvedUnits != null) {
      return _resolvedUnits;
    }
    if (result != null) {
      _resolvedUnits = result.unit.element.library.units;
      return _resolvedUnits;
    }
    LibraryElement libElem = libraryElement;
    if (libElem == null) {
      return null;
    }
    _resolvedUnits = <CompilationUnitElement>[];
    for (CompilationUnitElement unresolvedUnit in libElem.units) {
      CompilationUnit unit = await _computeAsync(
          this,
          new LibrarySpecificUnit(libElem.source, unresolvedUnit.source),
          RESOLVED_UNIT5,
          performance,
          'resolve library unit');
      checkAborted();
      CompilationUnitElement resolvedUnit = unit?.element;
      if (resolvedUnit != null) {
        _resolvedUnits.add(resolvedUnit);
      }
    }
    return _resolvedUnits;
  }

  /**
   * 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,
      {ResultDescriptor resultDescriptor}) async {
    request.checkAborted();
    CompletionPerformance performance =
        (request as CompletionRequestImpl).performance;
    const BUILD_REQUEST_TAG = 'build DartCompletionRequest';
    performance.logStartTime(BUILD_REQUEST_TAG);

    Source libSource;
    CompilationUnit unit;
    if (request.context == null) {
      unit = request.result.unit;
      // TODO(scheglov) support for parts
      libSource = unit.element.source;
    } else {
      Source source = request.source;
      AnalysisContext context = request.context;

      const PARSE_TAG = 'parse unit';
      performance.logStartTime(PARSE_TAG);
      unit = request.context.computeResult(source, PARSED_UNIT);
      performance.logElapseTime(PARSE_TAG);

      if (unit.directives.any((d) => d is PartOfDirective)) {
        List<Source> libraries = context.getLibrariesContaining(source);
        if (libraries.isNotEmpty) {
          libSource = libraries[0];
        }
      } else {
        libSource = source;
      }

      // Most (all?) contributors need declarations in scope to be resolved
      if (libSource != null) {
        unit = await _computeAsync(
            request,
            new LibrarySpecificUnit(libSource, source),
            resultDescriptor ?? RESOLVED_UNIT5,
            performance,
            'resolve declarations');
      }
    }

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

    // Resolve the expression in which the completion occurs
    // to properly determine if identifiers should be suggested
    // rather than invocations.
    if (dartRequest.target.maybeFunctionalArgument()) {
      AstNode node = dartRequest.target.containingNode.parent;
      if (node is Expression) {
        const FUNCTIONAL_ARG_TAG = 'resolve expression for isFunctionalArg';
        performance.logStartTime(FUNCTIONAL_ARG_TAG);
        await dartRequest.resolveContainingExpression(node);
        performance.logElapseTime(FUNCTIONAL_ARG_TAG);
        dartRequest.checkAborted();
      }
    }

    performance.logElapseTime(BUILD_REQUEST_TAG);
    return dartRequest;
  }

  static Future _computeAsync(
      CompletionRequest request,
      AnalysisTarget target,
      ResultDescriptor descriptor,
      CompletionPerformance performance,
      String perfTag) async {
    request.checkAborted();
    performance.logStartTime(perfTag);
    var result;
    try {
      result =
          await new AnalysisFutureHelper(request.context, target, descriptor)
              .computeAsync();
    } catch (e, s) {
      if (e is AnalysisNotScheduledError) {
        request.checkAborted();
      }
      throw new AnalysisException(
          'failed to $perfTag', new CaughtException(e, s));
    }
    request.checkAborted();
    return result;
  }
}

/**
 * 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);
        Keyword keyword = token.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);
  }
}
