// 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.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)) {
        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:
        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 NONE:
        if (Elements.isIdentifierName(identifier, "void")) {
          return typeProvider.getVoidType();
        }
        if (Elements.isIdentifierName(identifier, "dynamic")) {
          return typeProvider.getDynamicType();
        }
        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) {
    return node.accept(new Selector());
  }

  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());
  }

  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 && errorCode.getErrorSeverity() == ErrorSeverity.WARNING) {
      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();
    }
  }
}
