// 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/search/search_engine.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/context/context.dart'
    show AnalysisFutureHelper, AnalysisContextImpl;
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/engine.dart' hide AnalysisContextImpl;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/task/dart.dart';
import 'package:analysis_server/src/services/completion/optype.dart';

/**
 * [DartCompletionManager] determines if a completion request is Dart specific
 * and forwards those requests to all [DartCompletionContributor]s.
 */
class DartCompletionManager implements CompletionContributor {
  @override
  Future<List<CompletionSuggestion>> computeSuggestions(
      CompletionRequest request) async {
    if (!AnalysisEngine.isDartFileName(request.source.shortName)) {
      return EMPTY_LIST;
    }

    // Request Dart specific completions from each contributor
    DartCompletionRequestImpl dartRequest =
        await DartCompletionRequestImpl.from(request);
    List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
    for (DartCompletionContributor c in dartCompletionPlugin.contributors) {
      suggestions.addAll(await c.computeSuggestions(dartRequest));
    }
    return suggestions;
  }
}

/**
 * The information about a requested list of completions within a Dart file.
 */
class DartCompletionRequestImpl extends CompletionRequestImpl
    implements DartCompletionRequest {
  /**
   * Return a [Future] that completes with a newly created completion request
   * based on the given [request].
   */
  static Future<DartCompletionRequest> from(CompletionRequest request) async {
    Source source = request.source;
    AnalysisContext context = request.context;
    CompilationUnit unit = request.context.computeResult(source, PARSED_UNIT);

    Source libSource;
    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 new AnalysisFutureHelper<CompilationUnit>(context,
              new LibrarySpecificUnit(libSource, source), RESOLVED_UNIT3)
          .computeAsync();
    }

    return new DartCompletionRequestImpl._(
        request.context,
        request.resourceProvider,
        request.searchEngine,
        libSource,
        request.source,
        request.offset,
        unit);
  }

  DartCompletionRequestImpl._(
      AnalysisContext context,
      ResourceProvider resourceProvider,
      SearchEngine searchEngine,
      this.librarySource,
      Source source,
      int offset,
      CompilationUnit unit)
      : super(context, resourceProvider, searchEngine, source, offset) {
    _updateTargets(unit);
  }

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

  @override
  Expression dotTarget;

  @override
  Source librarySource;

  OpType _opType;

  @override
  CompletionTarget target;

  @override
  bool get includeIdentifiers {
    if (_opType == null) {
      _opType = new OpType.forCompletion(target, offset);
    }
    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) {
      Source coreUri = context.sourceFactory.forUri('dart:core');
      LibraryElement coreLib = context.getLibraryElement(coreUri);
      _objectType = coreLib.getType('Object').type;
    }
    return _objectType;
  }

  @override
  Future<List<Directive>> resolveDirectives() async {
    CompilationUnit libUnit;
    if (librarySource == source) {
      libUnit = target.unit;
    } else if (librarySource != null) {
      // TODO(danrubel) only resolve the directives
      libUnit = await new AnalysisFutureHelper<CompilationUnit>(
              context,
              new LibrarySpecificUnit(librarySource, librarySource),
              RESOLVED_UNIT3)
          .computeAsync();
    }
    return libUnit?.directives;
  }

  @override
  Future resolveExpression(Expression expression) async {
    // Return immediately if the expression has already been resolved
    if (expression.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 complilation unit
    CompilationUnit resolvedUnit =
        await new AnalysisFutureHelper<CompilationUnit>(context,
                new LibrarySpecificUnit(librarySource, source), RESOLVED_UNIT)
            .computeAsync();

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

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