// 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.common.annotations.VisibleForTesting;
import com.google.dart.compiler.DartCompilationError;
import com.google.dart.compiler.DartCompilerContext;
import com.google.dart.compiler.ErrorCode;
import com.google.dart.compiler.ErrorSeverity;
import com.google.dart.compiler.PackageLibraryManager;
import com.google.dart.compiler.Source;
import com.google.dart.compiler.SubSystem;
import com.google.dart.compiler.ast.ASTVisitor;
import com.google.dart.compiler.ast.DartClassTypeAlias;
import com.google.dart.compiler.ast.DartFunctionExpression;
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.DartPropertyAccess;
import com.google.dart.compiler.ast.DartSyntheticErrorIdentifier;
import com.google.dart.compiler.ast.DartTypeNode;
import com.google.dart.compiler.ast.LibraryUnit;
import com.google.dart.compiler.ast.Modifiers;
import com.google.dart.compiler.common.HasSourceInfo;
import com.google.dart.compiler.common.SourceInfo;
import com.google.dart.compiler.parser.DartParser;
import com.google.dart.compiler.type.InterfaceType;
import com.google.dart.compiler.type.Type;
import com.google.dart.compiler.type.TypeKind;
import com.google.dart.compiler.type.TypeVariable;
import com.google.dart.compiler.type.Types;

import java.util.Arrays;
import java.util.List;


/**
 * Resolution context for resolution of Dart programs. The initial context is
 * derived from the library scope, which is then extended with class scope,
 * method scope, and block scope as the program is traversed.
 */
@VisibleForTesting
public class ResolutionContext implements ResolutionErrorListener {
  private Scope scope;
  private final DartCompilerContext context;
  private final CoreTypeProvider typeProvider;
  private final boolean suppressSdkWarnings;

  ResolutionContext(String name, LibraryElement library, DartCompilerContext context,
                    CoreTypeProvider typeProvider) {
    this(new Scope(name, library), context, typeProvider);
  }

  @VisibleForTesting
  public ResolutionContext(Scope scope, DartCompilerContext context,
                           CoreTypeProvider typeProvider) {
    this.scope = scope;
    this.context = context;
    this.typeProvider = typeProvider;
    this.suppressSdkWarnings = context.getCompilerConfiguration().getCompilerOptions()
        .suppressSdkWarnings();
  }

  ResolutionContext(LibraryUnit unit, DartCompilerContext context, CoreTypeProvider typeProvider) {
    this(unit.getElement().getScope(), context, typeProvider);
  }

  @VisibleForTesting
  public ResolutionContext extend(ClassElement element) {
    return new ResolutionContext(new ClassScope(element, scope), context, typeProvider);
  }

  ResolutionContext extend(String name) {
    return new ResolutionContext(new Scope(name, scope.getLibrary(), scope), context, typeProvider);
  }

  Scope getScope() {
    return scope;
  }

  void declare(Element element, ErrorCode errorCode) {
    String name = element.getName();
    Element existingLocalElement = scope.findLocalElement(name);
    // Check for duplicate declaration in the same scope.
    if (existingLocalElement != null && errorCode != null) {
      SourceInfo nameSourceInfo = element.getNameLocation();
      String existingLocation = Elements.getRelativeElementLocation(element, existingLocalElement);
      onError(nameSourceInfo, errorCode, name, existingLocation);
    }
    // Declare, may be hide existing element.
    scope.declareElement(name, element);
  }

  void pushScope(String name) {
    scope = new Scope(name, scope.getLibrary(), scope);
  }

  void popScope() {
    scope = scope.getParent();
  }

  /**
   * Returns <code>true</code> if the type is dynamic or an interface type where
   * {@link ClassElement#isInterface()} equals <code>isInterface</code>.
   */
  private boolean isInterfaceEquals(Type type, boolean isInterface) {
    switch (type.getKind()) {
      case DYNAMIC:
        // Considered to be a match.
        return true;

      case INTERFACE:
        InterfaceType interfaceType = (InterfaceType) type;
        ClassElement element = interfaceType.getElement();
        return (element != null && element.isInterface() == isInterface);

      default:
        break;
    }

    return false;
  }

  /**
   * Returns <code>true</code> if the type is dynamic or is a class type.
   */
  private boolean isClassType(Type type) {
    return isInterfaceEquals(type, false);
  }

  /**
   * Returns <code>true</code> if the type is a class or interface type.
   */
  private boolean isClassOrInterfaceType(Type type) {
    return type.getKind() == TypeKind.INTERFACE
        && ((InterfaceType) type).getElement() != null;
  }

  /**
   * To resolve the  class<typeparameters?> specified for extends on a class definition.
   */
  InterfaceType resolveClass(DartTypeNode node, boolean isStatic, boolean isFactory) {
    if (node == null) {
      return null;
    }

    Type type = resolveType(node, isStatic, isFactory, false, ResolverErrorCode.NO_SUCH_TYPE,
        ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
    if (!isClassType(type)) {
      onError(node.getIdentifier(), ResolverErrorCode.NOT_A_CLASS, type);
      type = typeProvider.getDynamicType();
    }

    node.setType(type);
    return (InterfaceType) type;
  }

  InterfaceType resolveInterface(DartTypeNode node, boolean isStatic, boolean isFactory) {
    Type type = resolveType(node, isStatic, isFactory, false,
        ResolverErrorCode.NO_SUCH_TYPE, ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
    if (type.getKind() != TypeKind.DYNAMIC && !isClassOrInterfaceType(type)) {
      onError(node.getIdentifier(), ResolverErrorCode.NOT_A_CLASS_OR_INTERFACE, type);
      type = typeProvider.getDynamicType();
    }

    node.setType(type);
    return (InterfaceType) type;
  }

  Type resolveType(DartTypeNode node, boolean isStatic, boolean isFactory, boolean isAnnotation,
      ErrorCode errorCode, ErrorCode wrongNumberErrorCode) {
    if (node == null) {
      return null;
    } else {
      Type type = resolveType(node, node.getIdentifier(), node.getTypeArguments(), isStatic,
          isFactory, isAnnotation, errorCode, wrongNumberErrorCode);
      recordTypeIdentifier(node.getIdentifier(), type.getElement());
      return type;
    }
  }

  protected <E extends Element> E recordTypeIdentifier(DartNode node, E element) {
    node.getClass();
    if (node instanceof DartPropertyAccess) {
      recordTypeIdentifier(((DartPropertyAccess)node).getQualifier(),
                           element.getEnclosingElement());
      return recordTypeIdentifier(((DartPropertyAccess)node).getName(), element);
    } else if (node instanceof DartIdentifier) {
      if (element == null) {
        // TypeAnalyzer will diagnose unresolved identifiers.
        return null;
      }
      node.setElement(element);
    } else {
      throw internalError(node, "Unexpected node: %s", node);
    }
    return element;
  }

  Type resolveType(DartNode diagnosticNode, DartNode identifier, List<DartTypeNode> typeArguments,
                   boolean isStatic, boolean isFactory, boolean isAnnotation, ErrorCode errorCode,
                   ErrorCode wrongNumberErrorCode) {
    // Built-in identifier can not be used as a type annotation.
    if (identifier instanceof DartIdentifier) {
      String name = ((DartIdentifier) identifier).getName();
      if (DartParser.PSEUDO_KEYWORDS_SET.contains(name) && !"dynamic".equals(name)
          && typeArguments.isEmpty()) {
        onError(identifier, ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, name);
        return Types.newDynamicType();
      }
    }
    // OK, valid name for type.
    Element element = resolveName(identifier);
    ElementKind elementKind = ElementKind.of(element);
    switch (elementKind) {
      case TYPE_VARIABLE: {
        TypeVariableElement typeVariableElement = (TypeVariableElement) element;
        if (!isFactory && isStatic &&
          typeVariableElement.getDeclaringElement().getKind().equals(ElementKind.CLASS)) {
          onError(identifier, ResolverErrorCode.TYPE_VARIABLE_IN_STATIC_CONTEXT, identifier);
          return typeProvider.getDynamicType();
        }
        return makeTypeVariable(typeVariableElement, typeArguments);
      }
      case CLASS:
      case FUNCTION_TYPE_ALIAS:
      case DYNAMIC:
        return instantiateParameterizedType(
            (ClassElement) element,
            diagnosticNode,
            typeArguments,
            isStatic,
            isFactory,
            errorCode,
            wrongNumberErrorCode);
      case DUPLICATE: {
        DuplicateElement duplicateElement = (DuplicateElement) element;
        List<String> locations = duplicateElement.getLocations();
        ResolverErrorCode duplicateErrorCode;
        if (isAnnotation) {
          duplicateErrorCode = ResolverErrorCode.DUPLICATE_IMPORTED_NAME_TYPE;
        } else {
          duplicateErrorCode = ResolverErrorCode.DUPLICATE_IMPORTED_NAME;
        }
        onError(identifier, duplicateErrorCode, element.getName(), locations.size(), locations);
        return typeProvider.getDynamicType();
      }
      case VOID:
        return typeProvider.getVoidType();
      case NONE:
        onError(identifier, errorCode, identifier);
        return typeProvider.getDynamicType();
      default:
        if (!(identifier instanceof DartSyntheticErrorIdentifier)) {
          if (errorCode.getSubSystem().equals(SubSystem.RESOLVER)) {
            onError(identifier, ResolverErrorCode.NOT_A_TYPE, identifier, elementKind);
          } else {
            onError(identifier, TypeErrorCode.NOT_A_TYPE, identifier, elementKind);
          }
        }
        return typeProvider.getDynamicType();
    }
  }

  InterfaceType instantiateParameterizedType(ClassElement element, DartNode node,
                                             List<DartTypeNode> typeArgumentNodes,
                                             boolean isStatic,
                                             boolean isFactory,
                                             ErrorCode errorCode,
                                             ErrorCode wrongNumberErrorCode) {
    List<Type> typeParameters = element.getTypeParameters();
    Type[] typeArguments;
    if (typeArgumentNodes == null || typeArgumentNodes.size() != typeParameters.size()) {
      typeArguments = new Type[typeParameters.size()];
      for (int i = 0; i < typeArguments.length; i++) {
        typeArguments[i] = typeProvider.getDynamicType();
      }
      if (typeArgumentNodes != null && typeArgumentNodes.size() > 0) {
        onError(node, wrongNumberErrorCode, element.getType(), typeArgumentNodes.size(), typeParameters.size());
      }
      int index = 0;
      if (typeArgumentNodes != null) {
        for (DartTypeNode typeNode : typeArgumentNodes) {
          Type type = resolveType(typeNode, isStatic, isFactory, false, errorCode,
              wrongNumberErrorCode);
          typeNode.setType(type);
          if (index < typeArguments.length) {
            typeArguments[index] = type;
          }
          index++;
        }
      }
    } else {
      typeArguments = new Type[typeArgumentNodes.size()];
      for (int i = 0; i < typeArguments.length; i++) {
        typeArguments[i] = resolveType(typeArgumentNodes.get(i), isStatic, isFactory, false, errorCode,
            wrongNumberErrorCode);
        typeArgumentNodes.get(i).setType(typeArguments[i]);
      }
    }
    return element.getType().subst(Arrays.asList(typeArguments), typeParameters);
  }

  private TypeVariable makeTypeVariable(TypeVariableElement element,
                                        List<DartTypeNode> typeArguments) {
    for (DartTypeNode typeArgument : typeArguments) {
      onError(typeArgument, ResolverErrorCode.EXTRA_TYPE_ARGUMENT);
    }
    return element.getTypeVariable();
  }

  /*
   * Interpret this node as a name reference,
   */
  Element resolveName(DartNode node) {
    Element result = node.accept(new Selector());
    if (result == null) {
      if (Elements.isIdentifierName(node, "void")) {
        return typeProvider.getVoidType().getElement();
      }
      if (Elements.isIdentifierName(node, "dynamic")) {
        return typeProvider.getDynamicType().getElement();
      }
    }
    return result;
  }

  MethodElement declareFunction(DartFunctionExpression node) {
    MethodElement element = Elements.methodFromFunctionExpression(node, Modifiers.NONE);
    if (node.getFunctionName() != null) {
      declare(
          element,
          ResolverErrorCode.DUPLICATE_FUNCTION_EXPRESSION);
    }
    return element;
  }

  void pushFunctionScope(DartFunctionExpression x) {
    pushScope(x.getFunctionName() == null ? "<function>" : x.getFunctionName());
  }

  void pushFunctionAliasScope(DartFunctionTypeAlias x) {
    pushScope(x.getName().getName() == null ? "<function>" : x.getName().getName());
  }
  
  void pushClassAliasScope(DartClassTypeAlias x) {
    pushScope(x.getName().getName() == null ? "<classTypeAlias>" : x.getName().getName());
  }

  AssertionError internalError(HasSourceInfo node, String message, Object... arguments) {
    message = String.format(message, arguments);
    context.onError(new DartCompilationError(node, ResolverErrorCode.INTERNAL_ERROR,
                                                      message));
    return new AssertionError("Internal error: " + message);
  }

  @Override
  public void onError(HasSourceInfo hasSourceInfo, ErrorCode errorCode, Object... arguments) {
    onError(hasSourceInfo.getSourceInfo(), errorCode, arguments);
  }

  public void onError(SourceInfo sourceInfo, ErrorCode errorCode, Object... arguments) {
    if (suppressSdkWarnings) {
      ErrorSeverity errorSeverity = errorCode.getErrorSeverity();
      if (errorSeverity == ErrorSeverity.WARNING || errorSeverity == ErrorSeverity.INFO) {
        Source source = sourceInfo.getSource();
        if (source != null && PackageLibraryManager.isDartUri(source.getUri())) {
          return;
        }
      }
    }
    context.onError(new DartCompilationError(sourceInfo, errorCode, arguments));
  }

  class Selector extends ASTVisitor<Element> {
    @Override
    public Element visitNode(DartNode node) {
      throw internalError(node, "Unexpected node: %s", node);
    }

    @Override
    public Element visitPropertyAccess(DartPropertyAccess node) {
      Element element = node.getQualifier().accept(this);
      if (element != null) {
        switch (element.getKind()) {
          case LIBRARY_PREFIX :
            Scope elementScope = ((LibraryPrefixElement) element).getScope();
            return elementScope.findElement(scope.getLibrary(), node.getPropertyName());
          case CLASS :
            return Elements.findElement((ClassElement) element, node.getPropertyName());
        }
      }
      return null;
    }

    @Override
    public Element visitIdentifier(DartIdentifier node) {
      String name = node.getName();
      return scope.findElement(scope.getLibrary(), name);
    }

    @Override
    public Element visitSyntheticErrorIdentifier(DartSyntheticErrorIdentifier node) {
      return Elements.dynamicElement();
    }
  }
}
