// Copyright (c) 2017, 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:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.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_plugin/protocol/protocol_common.dart' hide Element;
import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
import 'package:analyzer_plugin/src/utilities/completion/element_suggestion_builder.dart';
import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
import 'package:analyzer_plugin/utilities/completion/completion_core.dart';

/**
 * A contributor for calculating suggestions for inherited references.
 *
 * Plugin developers should extend this function and primarily
 * overload `computeSuggestions` (if needed).
 */
class InheritedReferenceContributor extends Object
    with ElementSuggestionBuilder
    implements CompletionContributor {
  @override
  LibraryElement containingLibrary;

  @override
  CompletionSuggestionKind kind;

  @override
  ResourceProvider resourceProvider;

  /**
   * Plugin contributors should primarily overload this function.
   * Should more parameters be needed for autocompletion needs, the
   * overloaded function should define those parameters and
   * call on `computeSuggestionsForClass`.
   */
  @override
  Future<void> computeSuggestions(
      DartCompletionRequest request, CompletionCollector collector) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    CompletionTarget target =
        new CompletionTarget.forOffset(request.result.unit, request.offset);
    OpType optype = new OpType.forCompletion(target, request.offset);
    if (!optype.includeIdentifiers) {
      return;
    }
    ClassDeclaration classDecl = _enclosingClass(target);
    if (classDecl == null || classDecl.declaredElement == null) {
      return;
    }
    containingLibrary = request.result.libraryElement;
    _computeSuggestionsForClass2(collector, target,
        resolutionMap.elementDeclaredByClassDeclaration(classDecl), optype);
  }

  /**
   * Clients should not overload this function.
   */
  Future<void> computeSuggestionsForClass(
    DartCompletionRequest request,
    CompletionCollector collector,
    ClassElement classElement, {
    AstNode entryPoint,
    bool skipChildClass,
    CompletionTarget target,
    OpType optype,
  }) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    target ??= new CompletionTarget.forOffset(
        request.result.unit, request.offset,
        entryPoint: entryPoint);
    optype ??= new OpType.forCompletion(target, request.offset);
    if (!optype.includeIdentifiers) {
      return;
    }
    if (classElement == null) {
      ClassDeclaration classDecl = _enclosingClass(target);
      if (classDecl == null || classDecl.declaredElement == null) {
        return;
      }
      classElement = resolutionMap.elementDeclaredByClassDeclaration(classDecl);
    }
    containingLibrary = request.result.libraryElement;
    _computeSuggestionsForClass2(collector, target, classElement, optype,
        skipChildClass: skipChildClass);
  }

  _addSuggestionsForType(InterfaceType type, OpType optype,
      {bool isFunctionalArgument: false}) {
    if (!isFunctionalArgument) {
      for (PropertyAccessorElement elem in type.accessors) {
        if (elem.isGetter) {
          if (optype.includeReturnValueSuggestions) {
            addSuggestion(elem);
          }
        } else {
          if (optype.includeVoidReturnSuggestions) {
            addSuggestion(elem);
          }
        }
      }
    }
    for (MethodElement elem in type.methods) {
      if (elem.returnType == null) {
        addSuggestion(elem);
      } else if (!elem.returnType.isVoid) {
        if (optype.includeReturnValueSuggestions) {
          addSuggestion(elem);
        }
      } else {
        if (optype.includeVoidReturnSuggestions) {
          addSuggestion(elem);
        }
      }
    }
  }

  void _computeSuggestionsForClass2(CompletionCollector collector,
      CompletionTarget target, ClassElement classElement, OpType optype,
      {bool skipChildClass: true}) {
    bool isFunctionalArgument = target.isFunctionalArgument();
    kind = isFunctionalArgument
        ? CompletionSuggestionKind.IDENTIFIER
        : CompletionSuggestionKind.INVOCATION;

    if (!skipChildClass) {
      _addSuggestionsForType(classElement.type, optype,
          isFunctionalArgument: isFunctionalArgument);
    }

    for (InterfaceType type in classElement.allSupertypes) {
      _addSuggestionsForType(type, optype,
          isFunctionalArgument: isFunctionalArgument);
    }
    for (CompletionSuggestion suggestion in suggestions) {
      collector.addSuggestion(suggestion);
    }
  }

  /**
   * Return the class containing the target
   * or `null` if the target is in a static method or field
   * or not in a class.
   */
  ClassDeclaration _enclosingClass(CompletionTarget target) {
    AstNode node = target.containingNode;
    while (node != null) {
      if (node is ClassDeclaration) {
        return node;
      }
      if (node is MethodDeclaration) {
        if (node.isStatic) {
          return null;
        }
      }
      if (node is FieldDeclaration) {
        if (node.isStatic) {
          return null;
        }
      }
      node = node.parent;
    }
    return null;
  }
}
