package org.checkerframework.framework.type.treeannotator;

import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.CompoundAssignmentTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.NewArrayTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.TypeCastTree;
import com.sun.source.tree.UnaryTree;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.type.TypeKind;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
import org.checkerframework.framework.type.QualifierHierarchy;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.Pair;
import org.checkerframework.javacutil.TypeKindUtils;

/**
 * {@link PropagationTreeAnnotator} adds qualifiers to types where the resulting type is a function
 * of an input type, e.g. the result of a binary operation is a LUB of the type of expressions in
 * the binary operation.
 *
 * <p>{@link PropagationTreeAnnotator} is generally run first by {@link ListTreeAnnotator} since the
 * trees it handles are not usually targets of {@code @DefaultFor}.
 *
 * <p>{@link PropagationTreeAnnotator} does not traverse trees deeply by default.
 *
 * @see TreeAnnotator
 */
public class PropagationTreeAnnotator extends TreeAnnotator {

  private final QualifierHierarchy qualHierarchy;

  /** Creates a {@link PropagationTreeAnnotator} for the given {@code atypeFactory}. */
  public PropagationTreeAnnotator(AnnotatedTypeFactory atypeFactory) {
    super(atypeFactory);
    this.qualHierarchy = atypeFactory.getQualifierHierarchy();
  }

  @Override
  public Void visitNewArray(NewArrayTree tree, AnnotatedTypeMirror type) {
    assert type.getKind() == TypeKind.ARRAY
        : "PropagationTreeAnnotator.visitNewArray: should be an array type";

    AnnotatedTypeMirror componentType = ((AnnotatedArrayType) type).getComponentType();

    // prev is the lub of the initializers if they exist, otherwise the current component type.
    Set<? extends AnnotationMirror> prev = null;
    if (tree.getInitializers() != null && !tree.getInitializers().isEmpty()) {
      // We have initializers, either with or without an array type.

      // TODO (issue #599): This only works at the top level.  It should work at all levels of
      // the array.
      for (ExpressionTree init : tree.getInitializers()) {
        AnnotatedTypeMirror initType = atypeFactory.getAnnotatedType(init);
        // initType might be a typeVariable, so use effectiveAnnotations.
        Set<AnnotationMirror> annos = initType.getEffectiveAnnotations();

        prev = (prev == null) ? annos : qualHierarchy.leastUpperBounds(prev, annos);
      }
    } else {
      prev = componentType.getAnnotations();
    }

    assert prev != null
        : "PropagationTreeAnnotator.visitNewArray: violated assumption about qualifiers";

    Pair<Tree, AnnotatedTypeMirror> context = atypeFactory.getVisitorState().getAssignmentContext();
    Set<? extends AnnotationMirror> post;

    if (context != null && context.second != null && context.second instanceof AnnotatedArrayType) {
      AnnotatedTypeMirror contextComponentType =
          ((AnnotatedArrayType) context.second).getComponentType();
      // Only compare the qualifiers that existed in the array type.
      // Defaulting wasn't performed yet, so prev might have fewer qualifiers than
      // contextComponentType, which would cause a failure.
      // TODO: better solution?
      boolean prevIsSubtype = true;
      for (AnnotationMirror am : prev) {
        if (contextComponentType.isAnnotatedInHierarchy(am)
            && !this.qualHierarchy.isSubtype(
                am, contextComponentType.getAnnotationInHierarchy(am))) {
          prevIsSubtype = false;
        }
      }
      // TODO: checking conformance of component kinds is a basic sanity check
      // It fails for array initializer expressions. Those should be handled nicer.
      if (contextComponentType.getKind() == componentType.getKind()
          && (prev.isEmpty()
              || (!contextComponentType.getAnnotations().isEmpty() && prevIsSubtype))) {
        post = contextComponentType.getAnnotations();
      } else {
        // The type of the array initializers is incompatible with the context type!
        // Somebody else will complain.
        post = prev;
      }
    } else {
      // No context is available - simply use what we have.
      post = prev;
    }
    // TODO (issue #599): This only works at the top level.  It should work at all levels of
    // the array.
    addAnnoOrBound(componentType, post);

    return null;
  }

  @Override
  public Void visitCompoundAssignment(CompoundAssignmentTree node, AnnotatedTypeMirror type) {
    if (hasPrimaryAnnotationInAllHierarchies(type)) {
      // If the type already has a primary annotation in all hierarchies, then the
      // propagated annotations won't be applied.  So don't compute them.
      return null;
    }
    AnnotatedTypeMirror rhs = atypeFactory.getAnnotatedType(node.getExpression());
    AnnotatedTypeMirror lhs = atypeFactory.getAnnotatedType(node.getVariable());
    Set<? extends AnnotationMirror> lubs =
        qualHierarchy.leastUpperBounds(
            rhs.getEffectiveAnnotations(), lhs.getEffectiveAnnotations());
    type.addMissingAnnotations(lubs);
    return null;
  }

  @Override
  public Void visitBinary(BinaryTree node, AnnotatedTypeMirror type) {
    if (hasPrimaryAnnotationInAllHierarchies(type)) {
      // If the type already has a primary annotation in all hierarchies, then the
      // propagated annotations won't be applied.  So don't compute them.
      // Also, calling getAnnotatedType on the left and right operands is potentially expensive.
      return null;
    }

    Pair<AnnotatedTypeMirror, AnnotatedTypeMirror> argTypes = atypeFactory.binaryTreeArgTypes(node);
    Set<? extends AnnotationMirror> lubs =
        qualHierarchy.leastUpperBounds(
            argTypes.first.getEffectiveAnnotations(), argTypes.second.getEffectiveAnnotations());
    type.addMissingAnnotations(lubs);

    return null;
  }

  @Override
  public Void visitUnary(UnaryTree node, AnnotatedTypeMirror type) {
    if (hasPrimaryAnnotationInAllHierarchies(type)) {
      // If the type already has a primary annotation in all hierarchies, then the
      // propagated annotations won't be applied.  So don't compute them.
      return null;
    }

    AnnotatedTypeMirror exp = atypeFactory.getAnnotatedType(node.getExpression());
    type.addMissingAnnotations(exp.getAnnotations());
    return null;
  }

  /*
   * TODO: would this make sense in general?
  @Override
  public Void visitConditionalExpression(ConditionalExpressionTree node, AnnotatedTypeMirror type) {
      if (!type.isAnnotated()) {
          AnnotatedTypeMirror a = typeFactory.getAnnotatedType(node.getTrueExpression());
          AnnotatedTypeMirror b = typeFactory.getAnnotatedType(node.getFalseExpression());
          Set<AnnotationMirror> lubs = qualHierarchy.leastUpperBounds(a.getEffectiveAnnotations(), b.getEffectiveAnnotations());
          type.replaceAnnotations(lubs);
      }
      return super.visitConditionalExpression(node, type);
  }*/

  @Override
  public Void visitTypeCast(TypeCastTree node, AnnotatedTypeMirror type) {
    if (hasPrimaryAnnotationInAllHierarchies(type)) {
      // If the type is already has a primary annotation in all hierarchies, then the
      // propagated annotations won't be applied.  So don't compute them.
      return null;
    }

    AnnotatedTypeMirror exprType = atypeFactory.getAnnotatedType(node.getExpression());
    if (type.getKind() == TypeKind.TYPEVAR) {
      if (exprType.getKind() == TypeKind.TYPEVAR) {
        // If both types are type variables, take the direct annotations.
        type.addMissingAnnotations(exprType.getAnnotations());
      }
      // else do nothing.
    } else {
      // Use effective annotations from the expression, to get upper bound of type variables.
      Set<AnnotationMirror> expressionAnnos = exprType.getEffectiveAnnotations();

      TypeKind castKind = type.getPrimitiveKind();
      if (castKind != null) {
        TypeKind exprKind = exprType.getPrimitiveKind();
        if (exprKind != null) {
          switch (TypeKindUtils.getPrimitiveConversionKind(exprKind, castKind)) {
            case WIDENING:
              expressionAnnos =
                  atypeFactory.getWidenedAnnotations(expressionAnnos, exprKind, castKind);
              break;
            case NARROWING:
              atypeFactory.getNarrowedAnnotations(expressionAnnos, exprKind, castKind);
              break;
            case SAME:
              // Nothing to do
              break;
          }
        }
      }

      // If the qualifier on the expression type is a supertype of the qualifier upper bound
      // of the cast type, then apply the bound as the default qualifier rather than the
      // expression qualifier.
      addAnnoOrBound(type, expressionAnnos);
    }

    return null;
  }

  private boolean hasPrimaryAnnotationInAllHierarchies(AnnotatedTypeMirror type) {
    boolean annotated = true;
    for (AnnotationMirror top : qualHierarchy.getTopAnnotations()) {
      if (type.getEffectiveAnnotationInHierarchy(top) == null) {
        annotated = false;
      }
    }
    return annotated;
  }

  /**
   * Adds the qualifiers in {@code annos} to {@code type} that are below the qualifier upper bound
   * of type and for which type does not already have annotation in the same hierarchy. If a
   * qualifier in {@code annos} is above the bound, then the bound is added to {@code type} instead.
   *
   * @param type annotations are added to this type
   * @param annos annotations to add to type
   */
  private void addAnnoOrBound(AnnotatedTypeMirror type, Set<? extends AnnotationMirror> annos) {
    Set<AnnotationMirror> boundAnnos =
        atypeFactory.getQualifierUpperBounds().getBoundQualifiers(type.getUnderlyingType());
    Set<AnnotationMirror> annosToAdd = AnnotationUtils.createAnnotationSet();
    for (AnnotationMirror boundAnno : boundAnnos) {
      AnnotationMirror anno = qualHierarchy.findAnnotationInSameHierarchy(annos, boundAnno);
      if (anno != null && !qualHierarchy.isSubtype(anno, boundAnno)) {
        annosToAdd.add(boundAnno);
      }
    }
    type.addMissingAnnotations(annosToAdd);
    type.addMissingAnnotations(annos);
  }
}
