// 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.computer.dart.local;

import 'dart:async';

import 'package:analysis_server/src/protocol.dart' as protocol show Element,
    ElementKind;
import 'package:analysis_server/src/protocol.dart' hide Element, ElementKind;
import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
import 'package:analysis_server/src/services/completion/suggestion_builder.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/scanner.dart';

/**
 * A computer for calculating `completion.getSuggestions` request results
 * for the local library in which the completion is requested.
 */
class LocalComputer extends DartCompletionComputer {

  @override
  bool computeFast(DartCompletionRequest request) {

    // Find the specific child [AstNode] that contains the completion offset
    // and collect suggestions starting with that node
    request.node.accept(new _LocalVisitor(request));

    // If the unit is not a part and does not reference any parts
    // then work is complete
    return !request.unit.directives.any(
        (Directive directive) =>
            directive is PartOfDirective || directive is PartDirective);
  }

  @override
  Future<bool> computeFull(DartCompletionRequest request) {
    // TODO: implement computeFull
    // include results from part files that are included in the library
    return new Future.value(false);
  }
}

/**
 * A visitor for collecting suggestions from the most specific child [AstNode]
 * that contains the completion offset to the [CompilationUnit].
 */
class _LocalVisitor extends GeneralizingAstVisitor<dynamic> {
  static const DYNAMIC = 'dynamic';

  static final TypeName NO_RETURN_TYPE = new TypeName(
      new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, '', 0)),
      null);

  static final TypeName STACKTRACE_TYPE = new TypeName(
      new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, 'StackTrace', 0)),
      null);

  final DartCompletionRequest request;
  bool typesOnly = false;
  bool excludeVoidReturn;

  _LocalVisitor(this.request) {
    excludeVoidReturn = _computeExcludeVoidReturn(request.node);
  }

  @override
  visitBlock(Block node) {
    node.statements.forEach((Statement stmt) {
      if (stmt.offset < request.offset) {
        if (stmt is LabeledStatement) {
          stmt.labels.forEach((Label label) {
//            _addSuggestion(label.label, CompletionSuggestionKind.LABEL);
          });
        } else if (stmt is VariableDeclarationStatement) {
          var varList = stmt.variables;
          if (varList != null) {
            varList.variables.forEach((VariableDeclaration varDecl) {
              if (varDecl.end < request.offset) {
                _addLocalVarSuggestion(varDecl.name, varList.type);
              }
            });
          }
        }
      }
    });
    visitNode(node);
  }

  @override
  visitCascadeExpression(CascadeExpression node) {
    Expression target = node.target;
    // This computer handles the expression
    // while InvocationComputer handles the cascade selector
    if (target != null && request.offset <= target.end) {
      visitNode(node);
    }
  }

  @override
  visitCatchClause(CatchClause node) {
    _addParamSuggestion(node.exceptionParameter, node.exceptionType);
    _addParamSuggestion(node.stackTraceParameter, STACKTRACE_TYPE);
    visitNode(node);
  }

  @override
  visitClassDeclaration(ClassDeclaration node) {
    _addClassDeclarationMembers(node);
    visitInheritedTypes(node, (ClassDeclaration classNode) {
      _addClassDeclarationMembers(classNode);
    }, (String typeName) {
      // ignored
    });
    visitNode(node);
  }

  @override
  visitCombinator(Combinator node) {
    // Handled by ImportedComputer
  }

  @override
  visitCompilationUnit(CompilationUnit node) {
    node.declarations.forEach((Declaration declaration) {
      if (declaration is ClassDeclaration) {
        _addClassSuggestion(declaration);
      } else if (declaration is EnumDeclaration) {
//        _addSuggestion(d.name, CompletionSuggestionKind.ENUM);
      } else if (declaration is FunctionDeclaration) {
        _addFunctionSuggestion(declaration);
      } else if (declaration is TopLevelVariableDeclaration) {
        _addTopLevelVarSuggestions(declaration.variables);
      } else if (declaration is ClassTypeAlias) {
        CompletionSuggestion suggestion = _addSuggestion(
            declaration.name,
            CompletionSuggestionKind.CLASS_ALIAS,
            null,
            null);
        if (suggestion != null) {
          suggestion.element = _createElement(
              protocol.ElementKind.CLASS_TYPE_ALIAS,
              declaration.name,
              null,
              NO_RETURN_TYPE,
              true,
              _isDeprecated(declaration.metadata));
        }
      } else if (declaration is FunctionTypeAlias) {
        CompletionSuggestion suggestion = _addSuggestion(
            declaration.name,
            CompletionSuggestionKind.FUNCTION_TYPE_ALIAS,
            declaration.returnType,
            null);
        if (suggestion != null) {
          suggestion.element = _createElement(
              protocol.ElementKind.FUNCTION_TYPE_ALIAS,
              declaration.name,
              null, // TODO (danrubel) determine parameters
              NO_RETURN_TYPE, // TODO (danrubel) determine return type
              true,
              _isDeprecated(declaration.metadata));
        }
      }
    });
  }

  @override
  visitExpressionStatement(ExpressionStatement node) {
    Expression expression = node.expression;
    if (expression is SimpleIdentifier) {
      if (expression.end < request.offset) {
        // TODO (danrubel) suggest possible names for variable declaration
        // based upon variable type
        return;
      }
    }
    visitNode(node);
  }

  @override
  visitForEachStatement(ForEachStatement node) {
    SimpleIdentifier id;
    TypeName type;
    DeclaredIdentifier loopVar = node.loopVariable;
    if (loopVar != null) {
      id = loopVar.identifier;
      type = loopVar.type;
    } else {
      id = node.identifier;
      type = null;
    }
    _addLocalVarSuggestion(id, type);
    visitNode(node);
  }

  @override
  visitForStatement(ForStatement node) {
    var varList = node.variables;
    if (varList != null) {
      varList.variables.forEach((VariableDeclaration varDecl) {
        _addLocalVarSuggestion(varDecl.name, varList.type);
      });
    }
    visitNode(node);
  }

  @override
  visitFunctionDeclaration(FunctionDeclaration node) {
    // This is added by the compilation unit containing it
    //_addSuggestion(node.name, CompletionSuggestionKind.FUNCTION);
    visitNode(node);
  }

  @override
  visitFunctionExpression(FunctionExpression node) {
    _addParamListSuggestions(node.parameters);
    visitNode(node);
  }

  @override
  visitInterpolationExpression(InterpolationExpression node) {
    visitNode(node);
  }

  @override
  visitMethodDeclaration(MethodDeclaration node) {
    _addParamListSuggestions(node.parameters);
    visitNode(node);
  }

  @override
  visitMethodInvocation(MethodInvocation node) {
    // InvocationComputer adds suggestions for method selector
    Token period = node.period;
    if (period != null && period.offset < request.offset) {
      ArgumentList argumentList = node.argumentList;
      if (argumentList == null || request.offset <= argumentList.offset) {
        return;
      }
    }
    visitNode(node);
  }

  @override
  visitNamespaceDirective(NamespaceDirective node) {
    // No suggestions
  }

  @override
  visitNode(AstNode node) {
    node.parent.accept(this);
  }

  @override
  visitPrefixedIdentifier(PrefixedIdentifier node) {
    // InvocationComputer adds suggestions for prefixed elements
    // but this computer adds suggestions for the prefix itself
    SimpleIdentifier prefix = node.prefix;
    if (prefix == null || request.offset <= prefix.end) {
      visitNode(node);
    }
  }

  @override
  visitPropertyAccess(PropertyAccess node) {
    // InvocationComputer adds suggestions for property access selector
  }

  @override
  visitStringInterpolation(StringInterpolation node) {
    visitNode(node);
  }

  @override
  visitStringLiteral(StringLiteral node) {
    // ignore
  }

  @override
  visitTypeName(TypeName node) {
    // If suggesting completions within a TypeName node
    // then limit suggestions to only types
    typesOnly = true;
    return visitNode(node);
  }

  @override
  visitVariableDeclaration(VariableDeclaration node) {
    // Do not add suggestions if editing the name in a var declaration
    SimpleIdentifier name = node.name;
    if (name == null ||
        name.offset < request.offset ||
        request.offset > name.end) {
      visitNode(node);
    }
  }

  void _addClassDeclarationMembers(ClassDeclaration node) {
    node.members.forEach((ClassMember classMbr) {
      if (classMbr is FieldDeclaration) {
        _addFieldSuggestions(node, classMbr);
      } else if (classMbr is MethodDeclaration) {
        _addMethodSuggestion(node, classMbr);
      }
    });
  }

  void _addClassSuggestion(ClassDeclaration declaration) {
    CompletionSuggestion suggestion =
        _addSuggestion(declaration.name, CompletionSuggestionKind.CLASS, null, null);
    if (suggestion != null) {
      suggestion.element = _createElement(
          protocol.ElementKind.CLASS,
          declaration.name,
          null,
          NO_RETURN_TYPE,
          declaration.isAbstract,
          _isDeprecated(declaration.metadata));
    }
  }

  void _addFieldSuggestions(ClassDeclaration node, FieldDeclaration fieldDecl) {
    if (typesOnly) {
      return;
    }
    bool isDeprecated = _isDeprecated(fieldDecl.metadata);
    fieldDecl.fields.variables.forEach((VariableDeclaration varDecl) {
      CompletionSuggestion suggestion = _addSuggestion(
          varDecl.name,
          CompletionSuggestionKind.GETTER,
          fieldDecl.fields.type,
          node);
      if (suggestion != null) {
        suggestion.element = _createElement(
            protocol.ElementKind.GETTER,
            varDecl.name,
            '()',
            fieldDecl.fields.type,
            false,
            isDeprecated || _isDeprecated(varDecl.metadata));
      }
    });
  }

  void _addFunctionSuggestion(FunctionDeclaration declaration) {
    if (typesOnly) {
      return;
    }
    if (excludeVoidReturn && _isVoid(declaration.returnType)) {
      return;
    }
    CompletionSuggestion suggestion = _addSuggestion(
        declaration.name,
        CompletionSuggestionKind.FUNCTION,
        declaration.returnType,
        null);
    if (suggestion != null) {
      suggestion.element = _createElement(
          protocol.ElementKind.FUNCTION,
          declaration.name,
          declaration.functionExpression.parameters.toSource(),
          declaration.returnType,
          false,
          _isDeprecated(declaration.metadata));
    }
  }

  void _addLocalVarSuggestion(SimpleIdentifier id, TypeName returnType) {
    if (typesOnly) {
      return;
    }
    CompletionSuggestion suggestion =
        _addSuggestion(id, CompletionSuggestionKind.LOCAL_VARIABLE, returnType, null);
    if (suggestion != null) {
      suggestion.element = _createElement(
          protocol.ElementKind.LOCAL_VARIABLE,
          id,
          null,
          returnType,
          false,
          false);
    }
  }

  void _addMethodSuggestion(ClassDeclaration node, MethodDeclaration classMbr) {
    if (typesOnly) {
      return;
    }
    protocol.ElementKind kind;
    CompletionSuggestionKind csKind;
    String parameters;
    if (classMbr.isGetter) {
      kind = protocol.ElementKind.GETTER;
      csKind = CompletionSuggestionKind.GETTER;
      parameters = '()';
    } else if (classMbr.isSetter) {
      if (excludeVoidReturn) {
        return;
      }
      kind = protocol.ElementKind.SETTER;
      csKind = CompletionSuggestionKind.SETTER;
      parameters = '(${classMbr.returnType.toSource()} value)';
    } else {
      if (excludeVoidReturn && _isVoid(classMbr.returnType)) {
        return;
      }
      kind = protocol.ElementKind.METHOD;
      csKind = CompletionSuggestionKind.METHOD;
      parameters = classMbr.parameters.toSource();
    }
    CompletionSuggestion suggestion =
        _addSuggestion(classMbr.name, csKind, classMbr.returnType, node);
    if (suggestion != null) {
      suggestion.element = _createElement(
          kind,
          classMbr.name,
          parameters,
          classMbr.returnType,
          classMbr.isAbstract,
          _isDeprecated(classMbr.metadata));
    }
  }

  void _addParamListSuggestions(FormalParameterList paramList) {
    if (typesOnly) {
      return;
    }
    if (paramList != null) {
      paramList.parameters.forEach((FormalParameter param) {
        NormalFormalParameter normalParam;
        if (param is DefaultFormalParameter) {
          normalParam = param.parameter;
        } else if (param is NormalFormalParameter) {
          normalParam = param;
        }
        TypeName type = null;
        if (normalParam is FieldFormalParameter) {
          type = normalParam.type;
        } else if (normalParam is FunctionTypedFormalParameter) {
          type = normalParam.returnType;
        } else if (normalParam is SimpleFormalParameter) {
          type = normalParam.type;
        }
        _addParamSuggestion(param.identifier, type);
      });
    }
  }

  void _addParamSuggestion(SimpleIdentifier identifier, TypeName type) {
    if (typesOnly) {
      return;
    }
    CompletionSuggestion suggestion =
        _addSuggestion(identifier, CompletionSuggestionKind.PARAMETER, type, null);
    if (suggestion != null) {
      suggestion.element = _createElement(
          protocol.ElementKind.PARAMETER,
          identifier,
          null,
          type,
          false,
          false);
    }
  }

  CompletionSuggestion _addSuggestion(SimpleIdentifier id,
      CompletionSuggestionKind kind, TypeName typeName, ClassDeclaration classDecl) {
    if (id != null) {
      String completion = id.name;
      if (completion != null && completion.length > 0 && completion != '_') {
        CompletionSuggestion suggestion = new CompletionSuggestion(
            kind,
            CompletionRelevance.DEFAULT,
            completion,
            completion.length,
            0,
            false,
            false);
        if (classDecl != null) {
          SimpleIdentifier identifier = classDecl.name;
          if (identifier != null) {
            String name = identifier.name;
            if (name != null && name.length > 0) {
              suggestion.declaringType = name;
            }
          }
        }
        if (typeName != null) {
          Identifier identifier = typeName.name;
          if (identifier != null) {
            String name = identifier.name;
            if (name != null && name.length > 0) {
              suggestion.returnType = name;
            }
          }
        }
        request.suggestions.add(suggestion);
        return suggestion;
      }
    }
    return null;
  }

  void _addTopLevelVarSuggestions(VariableDeclarationList varList) {
    if (typesOnly) {
      return;
    }
    if (varList != null) {
      bool isDeprecated = _isDeprecated(varList.metadata);
      varList.variables.forEach((VariableDeclaration varDecl) {
        CompletionSuggestion suggestion = _addSuggestion(
            varDecl.name,
            CompletionSuggestionKind.TOP_LEVEL_VARIABLE,
            varList.type,
            null);
        if (suggestion != null) {
          suggestion.element = _createElement(
              protocol.ElementKind.TOP_LEVEL_VARIABLE,
              varDecl.name,
              null,
              varList.type,
              false,
              isDeprecated || _isDeprecated(varDecl.metadata));
        }
      });
    }
  }

  bool _computeExcludeVoidReturn(AstNode node) {
    if (node is Block) {
      return false;
    } else if (node is SimpleIdentifier) {
      return node.parent is ExpressionStatement ? false : true;
    } else {
      return true;
    }
  }

  /**
   * Create a new protocol Element for inclusion in a completion suggestion.
   */
  protocol.Element _createElement(protocol.ElementKind kind,
      SimpleIdentifier id, String parameters, TypeName returnType,
      bool isAbstract, bool isDeprecated) {
    String name = id.name;
    int flags = protocol.Element.makeFlags(
        isAbstract: isAbstract,
        isDeprecated: isDeprecated,
        isPrivate: Identifier.isPrivateName(name));
    return new protocol.Element(
        kind,
        name,
        flags,
        parameters: parameters,
        returnType: _nameForType(returnType));
  }

  /**
   * Return `true` if the @deprecated annotation is present
   */
  bool _isDeprecated(NodeList<Annotation> metadata) =>
      metadata != null &&
          metadata.any(
              (Annotation a) => a.name is SimpleIdentifier && a.name.name == 'deprecated');

  bool _isVoid(TypeName returnType) {
    if (returnType != null) {
      Identifier id = returnType.name;
      if (id != null && id.name == 'void') {
        return true;
      }
    }
    return false;
  }

  /**
   * Return the name for the given type.
   */
  String _nameForType(TypeName type) {
    if (type == NO_RETURN_TYPE) {
      return null;
    }
    if (type == null) {
      return DYNAMIC;
    }
    Identifier id = type.name;
    if (id == null) {
      return DYNAMIC;
    }
    String name = id.name;
    if (name == null || name.length <= 0) {
      return DYNAMIC;
    }
    TypeArgumentList typeArgs = type.typeArguments;
    if (typeArgs != null) {
      //TODO (danrubel) include type arguments
    }
    return name;
  }
}
