package org.checkerframework.framework.type;

import com.sun.source.tree.AnnotatedTypeTree;
import com.sun.source.tree.ArrayTypeTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.IntersectionTypeTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.ParameterizedTypeTree;
import com.sun.source.tree.PrimitiveTypeTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.TypeParameterTree;
import com.sun.source.tree.UnionTypeTree;
import com.sun.source.tree.WildcardTree;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.TypeVariableSymbol;
import com.sun.tools.javac.code.Type.TypeVar;
import com.sun.tools.javac.code.Type.WildcardType;
import com.sun.tools.javac.tree.JCTree.JCWildcard;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeVariable;
import org.checkerframework.checker.interning.qual.FindDistinct;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedIntersectionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypesUtils;
import org.plumelib.util.CollectionsPlume;

/**
 * Converts type trees into AnnotatedTypeMirrors.
 *
 * @see org.checkerframework.framework.type.TypeFromTree
 */
class TypeFromTypeTreeVisitor extends TypeFromTreeVisitor {

  private final Map<Tree, AnnotatedTypeMirror> visitedBounds = new HashMap<>();

  @Override
  public AnnotatedTypeMirror visitAnnotatedType(AnnotatedTypeTree node, AnnotatedTypeFactory f) {
    AnnotatedTypeMirror type = visit(node.getUnderlyingType(), f);
    if (type == null) { // e.g., for receiver type
      type = f.toAnnotatedType(f.types.getNoType(TypeKind.NONE), false);
    }
    assert AnnotatedTypeFactory.validAnnotatedType(type);
    List<? extends AnnotationMirror> annos = TreeUtils.annotationsFromTree(node);

    if (type.getKind() == TypeKind.WILDCARD) {
      // Work-around for https://github.com/eisop/checker-framework/issues/17
      // For an annotated wildcard tree node, the type attached to the
      // node is a WildcardType with a correct bound (set to the type
      // variable which the wildcard instantiates). The underlying type is
      // also a WildcardType but with a bound of null. Here we update the
      // bound of the underlying WildcardType to be consistent.
      WildcardType wildcardAttachedToNode = (WildcardType) TreeUtils.typeOf(node);
      WildcardType underlyingWildcard = (WildcardType) type.getUnderlyingType();
      underlyingWildcard.withTypeVar(wildcardAttachedToNode.bound);
      // End of work-around

      final AnnotatedWildcardType wctype = ((AnnotatedWildcardType) type);
      final ExpressionTree underlyingTree = node.getUnderlyingType();

      if (underlyingTree.getKind() == Kind.UNBOUNDED_WILDCARD) {
        // primary annotations on unbounded wildcard types apply to both bounds
        wctype.getExtendsBound().addAnnotations(annos);
        wctype.getSuperBound().addAnnotations(annos);
      } else if (underlyingTree.getKind() == Kind.EXTENDS_WILDCARD) {
        wctype.getSuperBound().addAnnotations(annos);
      } else if (underlyingTree.getKind() == Kind.SUPER_WILDCARD) {
        wctype.getExtendsBound().addAnnotations(annos);
      } else {
        throw new BugInCF(
            "Unexpected kind for type.  node="
                + node
                + " type="
                + type
                + " kind="
                + underlyingTree.getKind());
      }
    } else {
      type.addAnnotations(annos);
    }

    return type;
  }

  @Override
  public AnnotatedTypeMirror visitArrayType(ArrayTypeTree node, AnnotatedTypeFactory f) {
    AnnotatedTypeMirror component = visit(node.getType(), f);

    AnnotatedTypeMirror result = f.type(node);
    assert result instanceof AnnotatedArrayType;
    ((AnnotatedArrayType) result).setComponentType(component);
    return result;
  }

  @Override
  public AnnotatedTypeMirror visitParameterizedType(
      ParameterizedTypeTree node, AnnotatedTypeFactory f) {

    ClassSymbol baseType = (ClassSymbol) TreeUtils.elementFromTree(node.getType());
    updateWildcardBounds(node.getTypeArguments(), baseType.getTypeParameters());

    List<AnnotatedTypeMirror> args =
        CollectionsPlume.mapList((Tree t) -> visit(t, f), node.getTypeArguments());

    AnnotatedTypeMirror result = f.type(node); // use creator?
    AnnotatedTypeMirror atype = visit(node.getType(), f);
    result.addAnnotations(atype.getAnnotations());
    // new ArrayList<>() type is AnnotatedExecutableType for some reason

    // Don't initialize the type arguments if they are empty. The type arguments might be a
    // diamond which should be inferred.
    if (result instanceof AnnotatedDeclaredType && !args.isEmpty()) {
      assert result instanceof AnnotatedDeclaredType : node + " --> " + result;
      ((AnnotatedDeclaredType) result).setTypeArguments(args);
    }
    return result;
  }

  /**
   * Work around a bug in javac 9 where sometimes the bound field is set to the transitive
   * supertype's type parameter instead of the type parameter which the wildcard directly
   * instantiates. See https://github.com/eisop/checker-framework/issues/18
   *
   * <p>Sets each wildcard type argument's bound from typeArgs to the corresponding type parameter
   * from typeParams.
   *
   * <p>If typeArgs.size() == 0 the method does nothing and returns. Otherwise, typeArgs.size() has
   * to be equal to typeParams.size().
   *
   * <p>For each wildcard type argument and corresponding type parameter, sets the
   * WildcardType.bound field to the corresponding type parameter, if and only if the owners of the
   * existing bound and the type parameter are different.
   *
   * <p>In scenarios where the bound's owner is the same, we don't want to replace a
   * capture-converted bound in the wildcard type with a non-capture-converted bound given by the
   * type parameter declaration.
   *
   * @param typeArgs the type of the arguments at (e.g., at the call side)
   * @param typeParams the type of the formal parameters (e.g., at the method declaration)
   */
  @SuppressWarnings("interning:not.interned") // workaround for javac bug
  private void updateWildcardBounds(
      List<? extends Tree> typeArgs, List<TypeVariableSymbol> typeParams) {
    if (typeArgs.isEmpty()) {
      // Nothing to do for empty type arguments.
      return;
    }
    assert typeArgs.size() == typeParams.size();

    Iterator<? extends Tree> typeArgsItr = typeArgs.iterator();
    Iterator<TypeVariableSymbol> typeParamsItr = typeParams.iterator();
    while (typeArgsItr.hasNext()) {
      Tree typeArg = typeArgsItr.next();
      TypeVariableSymbol typeParam = typeParamsItr.next();
      if (typeArg instanceof WildcardTree) {
        TypeVar typeVar = (TypeVar) typeParam.asType();
        WildcardType wcType = (WildcardType) ((JCWildcard) typeArg).type;
        if (wcType.bound != null
            && wcType.bound.tsym != null
            && typeVar.tsym != null
            && wcType.bound.tsym.owner != typeVar.tsym.owner) {
          wcType.withTypeVar(typeVar);
        }
      }
    }
  }

  @Override
  public AnnotatedTypeMirror visitPrimitiveType(PrimitiveTypeTree node, AnnotatedTypeFactory f) {
    return f.type(node);
  }

  @Override
  public AnnotatedTypeVariable visitTypeParameter(
      TypeParameterTree node, @FindDistinct AnnotatedTypeFactory f) {

    List<AnnotatedTypeMirror> bounds = new ArrayList<>(node.getBounds().size());
    for (Tree t : node.getBounds()) {
      AnnotatedTypeMirror bound;
      if (visitedBounds.containsKey(t) && f == visitedBounds.get(t).atypeFactory) {
        bound = visitedBounds.get(t);
      } else {
        visitedBounds.put(t, f.type(t));
        bound = visit(t, f);
        visitedBounds.remove(t);
      }
      bounds.add(bound);
    }

    AnnotatedTypeVariable result = (AnnotatedTypeVariable) f.type(node);
    List<? extends AnnotationMirror> annotations = TreeUtils.annotationsFromTree(node);
    result.getLowerBound().addAnnotations(annotations);

    switch (bounds.size()) {
      case 0:
        break;
      case 1:
        result.setUpperBound(bounds.get(0));
        break;
      default:
        AnnotatedIntersectionType intersection = (AnnotatedIntersectionType) result.getUpperBound();
        intersection.setBounds(bounds);
        intersection.copyIntersectionBoundAnnotations();
    }

    return result;
  }

  @Override
  public AnnotatedTypeMirror visitWildcard(WildcardTree node, AnnotatedTypeFactory f) {

    AnnotatedTypeMirror bound = visit(node.getBound(), f);

    AnnotatedTypeMirror result = f.type(node);
    assert result instanceof AnnotatedWildcardType;

    // for wildcards unlike type variables there are bounds that differ in type from
    // result.  These occur for RAW types.  In this case, use the newly created bound
    // rather than merging into result
    if (node.getKind() == Tree.Kind.SUPER_WILDCARD) {
      ((AnnotatedWildcardType) result).setSuperBound(bound);

    } else if (node.getKind() == Tree.Kind.EXTENDS_WILDCARD) {
      ((AnnotatedWildcardType) result).setExtendsBound(bound);
    }
    return result;
  }

  /**
   * If a tree is can be found for the declaration of the type variable {@code type}, then a {@link
   * AnnotatedTypeVariable} is returned with explicit annotations from the type variables declared
   * bounds. If a tree cannot be found, then {@code type}, converted to a use, is returned.
   *
   * @param type type variable used to find declaration tree
   * @param f annotated type factory
   * @return the AnnotatedTypeVariable from the declaration of {@code type} or {@code type} if no
   *     tree is found.
   */
  private AnnotatedTypeVariable getTypeVariableFromDeclaration(
      AnnotatedTypeVariable type, AnnotatedTypeFactory f) {
    TypeVariable typeVar = type.getUnderlyingType();
    TypeParameterElement tpe = (TypeParameterElement) typeVar.asElement();
    Element elt = tpe.getGenericElement();
    if (elt instanceof TypeElement) {
      TypeElement typeElt = (TypeElement) elt;
      int idx = typeElt.getTypeParameters().indexOf(tpe);
      ClassTree cls = (ClassTree) f.declarationFromElement(typeElt);
      if (cls == null || cls.getTypeParameters().isEmpty()) {
        // The type parameters in the source tree were already erased. The element already
        // contains all necessary information and we can return that.
        return type.asUse();
      }

      // `forTypeVariable` is called for Identifier, MemberSelect and UnionType trees,
      // none of which are declarations.  But `cls.getTypeParameters()` returns a list
      // of type parameter declarations (`TypeParameterTree`), so this  call
      // will return a declaration ATV.  So change it to a use.
      return visitTypeParameter(cls.getTypeParameters().get(idx), f).asUse();
    } else if (elt instanceof ExecutableElement) {
      ExecutableElement exElt = (ExecutableElement) elt;
      int idx = exElt.getTypeParameters().indexOf(tpe);
      MethodTree meth = (MethodTree) f.declarationFromElement(exElt);
      if (meth == null) {
        // throw new BugInCF("TypeFromTree.forTypeVariable: did not find source for: "
        //                   + elt);
        return type.asUse();
      }
      // This works the same as the case above.  Even though `meth` itself is not a
      // type declaration tree, the elements of `meth.getTypeParameters()` still are.
      AnnotatedTypeVariable result =
          visitTypeParameter(meth.getTypeParameters().get(idx), f).shallowCopy();
      result.setDeclaration(false);
      return result;
    } else if (TypesUtils.isCaptured(typeVar)) {
      // Captured types can have a generic element (owner) that is
      // not an element at all, namely Symtab.noSymbol.
      return type.asUse();
    } else {
      throw new BugInCF("TypeFromTree.forTypeVariable: not a supported element: " + elt);
    }
  }

  @Override
  public AnnotatedTypeMirror visitIdentifier(IdentifierTree node, AnnotatedTypeFactory f) {

    AnnotatedTypeMirror type = f.type(node);

    if (type.getKind() == TypeKind.TYPEVAR) {
      return getTypeVariableFromDeclaration((AnnotatedTypeVariable) type, f);
    }

    return type;
  }

  @Override
  public AnnotatedTypeMirror visitMemberSelect(MemberSelectTree node, AnnotatedTypeFactory f) {

    AnnotatedTypeMirror type = f.type(node);

    if (type.getKind() == TypeKind.TYPEVAR) {
      return getTypeVariableFromDeclaration((AnnotatedTypeVariable) type, f);
    }

    return type;
  }

  @Override
  public AnnotatedTypeMirror visitUnionType(UnionTypeTree node, AnnotatedTypeFactory f) {
    AnnotatedTypeMirror type = f.type(node);

    if (type.getKind() == TypeKind.TYPEVAR) {
      return getTypeVariableFromDeclaration((AnnotatedTypeVariable) type, f);
    }

    return type;
  }

  @Override
  public AnnotatedTypeMirror visitIntersectionType(
      IntersectionTypeTree node, AnnotatedTypeFactory f) {
    // This method is only called for IntersectionTypes in casts.  There is no IntersectionTypeTree
    // for a type variable bound that is an intersection.  See #visitTypeParameter.
    AnnotatedIntersectionType type = (AnnotatedIntersectionType) f.type(node);
    List<AnnotatedTypeMirror> bounds =
        CollectionsPlume.mapList((Tree boundTree) -> visit(boundTree, f), node.getBounds());
    type.setBounds(bounds);
    type.copyIntersectionBoundAnnotations();
    return type;
  }
}
