// Copyright (c) 2014, 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.contributor.dart.invocation;

import 'dart:async';

import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
import 'package:analysis_server/src/services/completion/local_declaration_visitor.dart';
import 'package:analysis_server/src/services/completion/local_suggestion_builder.dart';
import 'package:analysis_server/src/services/completion/optype.dart';
import 'package:analysis_server/src/services/completion/suggestion_builder.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';

import '../../protocol_server.dart'
    show CompletionSuggestion, CompletionSuggestionKind;
import '../../protocol_server.dart' as protocol;

/**
 * A contributor for calculating invocation / access suggestions
 * `completion.getSuggestions` request results.
 */
class PrefixedElementContributor extends DartCompletionContributor {
  SuggestionBuilder builder;

  @override
  bool computeFast(DartCompletionRequest request) {
    OpType optype = request.optype;
    if (optype.isPrefixed) {
      builder = request.target.containingNode
          .accept(new _InvocationAstVisitor(request));
      if (builder != null) {
        return builder.computeFast(request.target.containingNode);
      }
    }

    return true;
  }

  @override
  Future<bool> computeFull(DartCompletionRequest request) {
    if (builder != null) {
      return builder.computeFull(request.target.containingNode);
    }
    return new Future.value(false);
  }
}

class _ExpressionSuggestionBuilder implements SuggestionBuilder {
  final DartCompletionRequest request;

  _ExpressionSuggestionBuilder(this.request);

  @override
  bool computeFast(AstNode node) {
    return false;
  }

  @override
  Future<bool> computeFull(AstNode node) {
    if (node is MethodInvocation) {
      node = (node as MethodInvocation).realTarget;
    } else if (node is PropertyAccess) {
      node = (node as PropertyAccess).realTarget;
    }
    if (node is Identifier) {
      Element elem = node.bestElement;
      if (elem is ClassElement || elem is PrefixElement) {
        elem.accept(new _PrefixedIdentifierSuggestionBuilder(request));
        return new Future.value(true);
      }
    }
    if (node is Expression) {
      String containingMethodName;
      bool isSuper = node is SuperExpression;
      if (isSuper) {
        MethodDeclaration containingMethod =
            node.getAncestor((p) => p is MethodDeclaration);
        if (containingMethod != null) {
          SimpleIdentifier id = containingMethod.name;
          if (id != null) {
            containingMethodName = id.name;
          }
        }
      }
      InterfaceTypeSuggestionBuilder.suggestionsFor(request, node.bestType,
          isSuper: isSuper, containingMethodName: containingMethodName);
      return new Future.value(true);
    }
    return new Future.value(false);
  }
}

/**
 * A suggestion builder for 'this.' constructor arguments.
 */
class _FieldFormalSuggestionBuilder implements SuggestionBuilder {
  final DartCompletionRequest request;

  _FieldFormalSuggestionBuilder(this.request);

  @override
  bool computeFast(AstNode node) {
    if (node is FieldFormalParameter) {
      ConstructorDeclaration constructorDecl =
          node.getAncestor((p) => p is ConstructorDeclaration);
      if (constructorDecl != null) {

        // Compute fields already referenced
        List<String> referencedFields = new List<String>();
        for (FormalParameter param in constructorDecl.parameters.parameters) {
          if (param is FieldFormalParameter) {
            SimpleIdentifier fieldId = param.identifier;
            if (fieldId != null && fieldId != request.target.entity) {
              String fieldName = fieldId.name;
              if (fieldName != null && fieldName.length > 0) {
                referencedFields.add(fieldName);
              }
            }
          }
        }

        // Add suggestions for fields that are not already referenced
        ClassDeclaration classDecl =
            constructorDecl.getAncestor((p) => p is ClassDeclaration);
        for (ClassMember member in classDecl.members) {
          if (member is FieldDeclaration) {
            for (VariableDeclaration varDecl in member.fields.variables) {
              SimpleIdentifier fieldId = varDecl.name;
              if (fieldId != null) {
                String fieldName = fieldId.name;
                if (fieldName != null && fieldName.length > 0) {
                  if (!referencedFields.contains(fieldName)) {
                    CompletionSuggestion suggestion =
                        createFieldSuggestion(member, varDecl);
                    if (suggestion != null) {
                      request.addSuggestion(suggestion);
                    }
                  }
                }
              }
            }
          }
        }
      }
    } else {
      // This should never be called with a case not handled above.
      assert(false);
    }
    return true;
  }

  @override
  Future<bool> computeFull(AstNode node) {
    // This should never be called; we should always be able to compute
    // suggestions and return true in computeFast method.
    assert(false);
    return null;
  }
}

/**
 * An [AstNode] vistor for determining which suggestion builder
 * should be used to build invocation/access suggestions.
 */
class _InvocationAstVisitor extends GeneralizingAstVisitor<SuggestionBuilder> {
  final DartCompletionRequest request;

  _InvocationAstVisitor(this.request);

  @override
  SuggestionBuilder visitConstructorName(ConstructorName node) {
    // some PrefixedIdentifier nodes are transformed into
    // ConstructorName nodes during the resolution process.
    return new _PrefixedIdentifierSuggestionBuilder(request);
  }

  @override
  SuggestionBuilder visitFieldFormalParameter(FieldFormalParameter node) {
    return new _FieldFormalSuggestionBuilder(request);
  }

  @override
  SuggestionBuilder visitMethodInvocation(MethodInvocation node) {
    return new _ExpressionSuggestionBuilder(request);
  }

  @override
  SuggestionBuilder visitNode(AstNode node) {
    return null;
  }

  @override
  SuggestionBuilder visitPrefixedIdentifier(PrefixedIdentifier node) {
    // some PrefixedIdentifier nodes are transformed into
    // ConstructorName nodes during the resolution process.
    return new _PrefixedIdentifierSuggestionBuilder(request);
  }

  @override
  SuggestionBuilder visitPropertyAccess(PropertyAccess node) {
    return new _ExpressionSuggestionBuilder(request);
  }
}

/**
 * An [AstVisitor] which looks for a declaration with the given name
 * and if found, tries to determine a type for that declaration.
 */
class _LocalBestTypeVisitor extends LocalDeclarationVisitor {

  /**
   * The name for the declaration to be found.
   */
  final String targetName;

  /**
   * The best type for the found declaration,
   * or `null` if no declaration found or failed to determine a type.
   */
  DartType typeFound;

  /**
   * Construct a new instance to search for a declaration
   */
  _LocalBestTypeVisitor(this.targetName, int offset) : super(offset);

  @override
  void declaredClass(ClassDeclaration declaration) {
    if (declaration.name.name == targetName) {
      // no type
      finished();
    }
  }

  @override
  void declaredClassTypeAlias(ClassTypeAlias declaration) {
    if (declaration.name.name == targetName) {
      // no type
      finished();
    }
  }

  @override
  void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
    if (varDecl.name.name == targetName) {
      // Type provided by the element in computeFull above
      finished();
    }
  }

  @override
  void declaredFunction(FunctionDeclaration declaration) {
    if (declaration.name.name == targetName) {
      TypeName typeName = declaration.returnType;
      if (typeName != null) {
        typeFound = typeName.type;
      }
      finished();
    }
  }

  @override
  void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {
    if (declaration.name.name == targetName) {
      TypeName typeName = declaration.returnType;
      if (typeName != null) {
        typeFound = typeName.type;
      }
      finished();
    }
  }

  @override
  void declaredLabel(Label label, bool isCaseLabel) {
    if (label.label.name == targetName) {
      // no type
      finished();
    }
  }

  @override
  void declaredLocalVar(SimpleIdentifier name, TypeName type) {
    if (name.name == targetName) {
      typeFound = name.bestType;
      finished();
    }
  }

  @override
  void declaredMethod(MethodDeclaration declaration) {
    if (declaration.name.name == targetName) {
      TypeName typeName = declaration.returnType;
      if (typeName != null) {
        typeFound = typeName.type;
      }
      finished();
    }
  }

  @override
  void declaredParam(SimpleIdentifier name, TypeName type) {
    if (name.name == targetName) {
      // Type provided by the element in computeFull above
      finished();
    }
  }

  @override
  void declaredTopLevelVar(
      VariableDeclarationList varList, VariableDeclaration varDecl) {
    if (varDecl.name.name == targetName) {
      // Type provided by the element in computeFull above
      finished();
    }
  }
}

/**
 * An [Element] visitor for determining the appropriate invocation/access
 * suggestions based upon the element for which the completion is requested.
 */
class _PrefixedIdentifierSuggestionBuilder
    extends GeneralizingElementVisitor<Future<bool>>
    implements SuggestionBuilder {
  final DartCompletionRequest request;

  _PrefixedIdentifierSuggestionBuilder(this.request);

  @override
  bool computeFast(AstNode node) {
    return false;
  }

  @override
  Future<bool> computeFull(AstNode node) {
    if (node is ConstructorName) {
      // some PrefixedIdentifier nodes are transformed into
      // ConstructorName nodes during the resolution process.
      return new NamedConstructorSuggestionBuilder(request).computeFull(node);
    }
    if (node is PrefixedIdentifier) {
      SimpleIdentifier prefix = node.prefix;
      if (prefix != null) {
        Element element = prefix.bestElement;
        DartType type = prefix.bestType;
        if (element is! ClassElement) {
          if (type == null || type.isDynamic) {
            //
            // Given `g. int y = 0;`, the parser interprets `g` as a prefixed
            // identifier with no type.
            // If the user is requesting completions for `g`,
            // then check for a function, getter, or similar with a type.
            //
            _LocalBestTypeVisitor visitor =
                new _LocalBestTypeVisitor(prefix.name, request.offset);
            if (visitor.visit(prefix)) {
              type = visitor.typeFound;
            }
          }
          if (type != null && !type.isDynamic) {
            InterfaceTypeSuggestionBuilder.suggestionsFor(request, type);
            return new Future.value(true);
          }
        }
        if (element != null) {
          return element.accept(this);
        }
      }
    }
    return new Future.value(false);
  }

  @override
  Future<bool> visitClassElement(ClassElement element) {
    if (element != null) {
      InterfaceType type = element.type;
      if (type != null) {
        StaticClassElementSuggestionBuilder.suggestionsFor(
            request, type.element);
      }
    }
    return new Future.value(false);
  }

  @override
  Future<bool> visitElement(Element element) {
    return new Future.value(false);
  }

  @override
  Future<bool> visitPrefixElement(PrefixElement element) {
    bool modified = false;
    // Find the import directive with the given prefix
    for (Directive directive in request.unit.directives) {
      if (directive is ImportDirective) {
        if (directive.prefix != null) {
          if (directive.prefix.name == element.name) {
            // Suggest elements from the imported library
            LibraryElement library = directive.uriElement;
            LibraryElementSuggestionBuilder.suggestionsFor(request,
                CompletionSuggestionKind.INVOCATION, library,
                request.target.containingNode.parent is TypeName);
            modified = true;
            if (directive.deferredKeyword != null) {
              String completion = 'loadLibrary';
              CompletionSuggestion suggestion = new CompletionSuggestion(
                  CompletionSuggestionKind.INVOCATION, DART_RELEVANCE_DEFAULT,
                  completion, completion.length, 0, false, false,
                  parameterNames: [],
                  parameterTypes: [],
                  requiredParameterCount: 0,
                  hasNamedParameters: false,
                  returnType: 'void');
              suggestion.element = new protocol.Element(
                  protocol.ElementKind.FUNCTION, completion,
                  protocol.Element.makeFlags(),
                  parameters: '()', returnType: 'void');
              request.addSuggestion(suggestion);
            }
          }
        }
      }
    }
    return new Future.value(modified);
  }

  @override
  Future<bool> visitPropertyAccessorElement(PropertyAccessorElement element) {
    if (element != null) {
      PropertyInducingElement elemVar = element.variable;
      if (elemVar != null) {
        InterfaceTypeSuggestionBuilder.suggestionsFor(request, elemVar.type);
      }
      return new Future.value(true);
    }
    return new Future.value(false);
  }

  @override
  Future<bool> visitVariableElement(VariableElement element) {
    InterfaceTypeSuggestionBuilder.suggestionsFor(request, element.type);
    return new Future.value(true);
  }
}
