// 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/standard_ast_factory.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.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 =
          resolutionMap.elementDeclaredByCompilationUnit(result.unit).context;
      _coreLib = context.typeProvider.objectType.element.library;
    } else {
      Source coreUri = sourceFactory.forUri('dart:core');
      _coreLib = context.computeLibraryElement(coreUri);
    }
    return _coreLib;
  }

  @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.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 {
    if (result != null) {
      return result.content;
    } else {
      return 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;
    }
    if (result != null) {
      _resolvedImports = libElem.imports;
    } else {
      _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 = resolutionMap
          .elementDeclaredByCompilationUnit(result.unit)
          .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 = resolutionMap.elementDeclaredByCompilationUnit(unit).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 =
            astFactory.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);
  }
}
