// Copyright (c) 2012, 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.

package com.google.dart.compiler.resolver;

import com.google.dart.compiler.ErrorCode;
import com.google.dart.compiler.ast.ASTNodes;
import com.google.dart.compiler.ast.ASTVisitor;
import com.google.dart.compiler.ast.DartCatchBlock;
import com.google.dart.compiler.ast.DartFunction;
import com.google.dart.compiler.ast.DartFunctionTypeAlias;
import com.google.dart.compiler.ast.DartIdentifier;
import com.google.dart.compiler.ast.DartNode;
import com.google.dart.compiler.ast.DartParameter;
import com.google.dart.compiler.ast.DartThisExpression;
import com.google.dart.compiler.ast.DartTypeNode;
import com.google.dart.compiler.ast.DartTypeParameter;
import com.google.dart.compiler.type.FunctionType;
import com.google.dart.compiler.type.Type;
import com.google.dart.compiler.type.Types;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * Shared visitor between Resolver and MemberBuilder.
 */
abstract class ResolveVisitor extends ASTVisitor<Element> {
  private final CoreTypeProvider typeProvider;

  ResolveVisitor(CoreTypeProvider typeProvider) {
    this.typeProvider = typeProvider;
  }

  abstract ResolutionContext getContext();

  final MethodElement resolveFunction(DartFunction node, MethodElement element) {
    for (DartParameter parameter : node.getParameters()) {
      Elements.addParameter(element, (VariableElement) parameter.accept(this));
    }
    resolveFunctionWithParameters(node, element);
    Type returnType =
        resolveType(
            node.getReturnTypeNode(),
            element.getModifiers().isStatic(),
            element.getModifiers().isFactory(),
            true,
            TypeErrorCode.NO_SUCH_TYPE,
            TypeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
    ClassElement functionElement = typeProvider.getFunctionType().getElement();
    FunctionType type = Types.makeFunctionType(getContext(), functionElement,
                                               element.getParameters(), returnType);
    Elements.setType(element, type);
    for (DartParameter parameter : node.getParameters()) {
      if (!(parameter.getQualifier() instanceof DartThisExpression) &&
          DartIdentifier.isPrivateName(parameter.getElement().getName())) {
        if (parameter.getModifiers().isOptional()) {
          getContext().onError(parameter.getName(),
              ResolverErrorCode.OPTIONAL_PARAMETERS_CANNOT_START_WITH_UNDER);
        }
        if (parameter.getModifiers().isNamed()) {
          getContext().onError(parameter.getName(),
              ResolverErrorCode.NAMED_PARAMETERS_CANNOT_START_WITH_UNDER);
        }
      }
    }
    return element;
  }

  /**
   * Allows subclass to process {@link DartFunction} element with parameters, but before
   * {@link FunctionType} is created for it.
   */
  protected void resolveFunctionWithParameters(DartFunction node, MethodElement element) {
  }

  final FunctionAliasElement resolveFunctionAlias(DartFunctionTypeAlias node) {
    HashSet<String> parameterNames = new HashSet<String>();
    for (DartTypeParameter parameter : node.getTypeParameters()) {
      TypeVariableElement typeVar = (TypeVariableElement) parameter.getElement();
      String parameterName = typeVar.getName();
      if (parameterNames.contains(parameterName)) {
        getContext().onError(parameter, ResolverErrorCode.DUPLICATE_TYPE_VARIABLE, parameterName);
      } else {
        parameterNames.add(parameterName);
      }
      getContext().getScope().declareElement(parameterName, typeVar);
    }
    return null;
  }

  @Override
  public Element visitParameter(DartParameter node) {
    ErrorCode typeErrorCode;
    ErrorCode wrongNumberErrorCode;
    if (node.getParent() instanceof DartCatchBlock) {
      typeErrorCode = ResolverErrorCode.NO_SUCH_TYPE;
      wrongNumberErrorCode = ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS;
    } else {
      typeErrorCode = TypeErrorCode.NO_SUCH_TYPE;
      wrongNumberErrorCode = TypeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS;
    }
    Type type = resolveType(node.getTypeNode(), ASTNodes.isStaticContext(node),
        ASTNodes.isFactoryContext(node), true, typeErrorCode, wrongNumberErrorCode);
    VariableElement element =
        Elements.parameterElement(
            getEnclosingElement(),
            node,
            node.getParameterName(),
            node.getModifiers());
    List<DartParameter> functionParameters = node.getFunctionParameters();
    if (functionParameters != null) {
      List<VariableElement> parameterElements =
          new ArrayList<VariableElement>(functionParameters.size());
      for (DartParameter parameter: functionParameters) {
        parameterElements.add((VariableElement) parameter.accept(this));
      }
      ClassElement functionElement = typeProvider.getFunctionType().getElement();
      type = Types.makeFunctionType(getContext(), functionElement, parameterElements, type);
    }
    Elements.setType(element, type);
    recordElement(node.getName(), element);
    return recordElement(node, element);
  }

  protected EnclosingElement getEnclosingElement() {
    return null;
  }

  final Type resolveType(DartTypeNode node, boolean isStatic, boolean isFactory,
      boolean isAnnotation, ErrorCode errorCode, ErrorCode wrongNumberErrorCode) {
    if (node == null) {
      return getTypeProvider().getDynamicType();
    }
//    assert node.getType() == null || node.getType() instanceof DynamicType;
    Type type = getContext().resolveType(node, isStatic, isFactory, isAnnotation, errorCode,
        wrongNumberErrorCode);
    if (type == null) {
      type = getTypeProvider().getDynamicType();
    }
    node.setType(type);
    Element element = type.getElement();
    recordElement(node.getIdentifier(), element);
    if (element != null && element.getMetadata().isDeprecated()) {
      getContext().onError(node.getIdentifier(), TypeErrorCode.DEPRECATED_ELEMENT,
         Elements.getDeprecatedElementTitle(element));
    }
    return type;
  }

  protected <E extends Element> E recordElement(DartNode node, E element) {
    node.getClass();
    if (element == null) {
      // TypeAnalyzer will diagnose unresolved identifiers.
      return null;
    }
    node.setElement(element);
    return element;
  }

  CoreTypeProvider getTypeProvider() {
    return typeProvider;
  }
}
