package org.checkerframework.checker.nullness;

import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import org.checkerframework.checker.initialization.InitializationTransfer;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.nullness.qual.PolyNull;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.dataflow.analysis.ConditionalTransferResult;
import org.checkerframework.dataflow.analysis.TransferInput;
import org.checkerframework.dataflow.analysis.TransferResult;
import org.checkerframework.dataflow.cfg.node.ArrayAccessNode;
import org.checkerframework.dataflow.cfg.node.FieldAccessNode;
import org.checkerframework.dataflow.cfg.node.InstanceOfNode;
import org.checkerframework.dataflow.cfg.node.MethodAccessNode;
import org.checkerframework.dataflow.cfg.node.MethodInvocationNode;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.dataflow.cfg.node.NullLiteralNode;
import org.checkerframework.dataflow.cfg.node.ReturnNode;
import org.checkerframework.dataflow.cfg.node.ThrowNode;
import org.checkerframework.dataflow.expression.JavaExpression;
import org.checkerframework.dataflow.expression.LocalVariable;
import org.checkerframework.framework.flow.CFAbstractAnalysis;
import org.checkerframework.framework.flow.CFAbstractStore;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.type.GenericAnnotatedTypeFactory;
import org.checkerframework.framework.type.visitor.SimpleAnnotatedTypeScanner;
import org.checkerframework.framework.util.AnnotatedTypes;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypesUtils;

/**
 * Transfer function for the non-null type system. Performs the following refinements:
 *
 * <ol>
 *   <li>After an expression is compared with the {@code null} literal, then that expression can
 *       safely be considered {@link NonNull} if the result of the comparison is false or {@link
 *       Nullable} if the result is true.
 *   <li>If an expression is dereferenced, then it can safely be assumed to non-null in the future.
 *       If it would not be, then the dereference would have raised a {@link NullPointerException}.
 *   <li>Tracks whether {@link PolyNull} is known to be {@link NonNull} or {@link Nullable} (or not
 *       known to be either).
 * </ol>
 */
public class NullnessTransfer
    extends InitializationTransfer<NullnessValue, NullnessTransfer, NullnessStore> {

  /** The @{@link NonNull} annotation. */
  protected final AnnotationMirror NONNULL;
  /** The @{@link Nullable} annotation. */
  protected final AnnotationMirror NULLABLE;
  /** The @{@link PolyNull} annotation. */
  protected final AnnotationMirror POLYNULL;

  /**
   * Java's Map interface.
   *
   * <p>The qualifiers in this type don't matter -- it is not used as a fully-annotated
   * AnnotatedDeclaredType, but just passed to asSuper().
   */
  protected final AnnotatedDeclaredType MAP_TYPE;

  /** The type factory for the nullness analysis that was passed to the constructor. */
  protected final GenericAnnotatedTypeFactory<
          NullnessValue,
          NullnessStore,
          NullnessTransfer,
          ? extends CFAbstractAnalysis<NullnessValue, NullnessStore, NullnessTransfer>>
      nullnessTypeFactory;

  /**
   * The type factory for the map key analysis, or null if the Map Key Checker should not be run.
   */
  protected final @Nullable KeyForAnnotatedTypeFactory keyForTypeFactory;

  /** Create a new NullnessTransfer for the given analysis. */
  public NullnessTransfer(NullnessAnalysis analysis) {
    super(analysis);
    this.nullnessTypeFactory = analysis.getTypeFactory();
    Elements elements = nullnessTypeFactory.getElementUtils();
    BaseTypeChecker checker = nullnessTypeFactory.getChecker();
    if (checker.hasOption("assumeKeyFor")) {
      this.keyForTypeFactory = null;
    } else {
      // It is error-prone to put a type factory in a field.  It is OK here because
      // keyForTypeFactory is used only to call methods isMapGet() and isKeyForMap().
      this.keyForTypeFactory = checker.getTypeFactoryOfSubchecker(KeyForSubchecker.class);
    }

    NONNULL = AnnotationBuilder.fromClass(elements, NonNull.class);
    NULLABLE = AnnotationBuilder.fromClass(elements, Nullable.class);
    POLYNULL = AnnotationBuilder.fromClass(elements, PolyNull.class);

    MAP_TYPE =
        (AnnotatedDeclaredType)
            AnnotatedTypeMirror.createType(
                TypesUtils.typeFromClass(Map.class, analysis.getTypes(), elements),
                nullnessTypeFactory,
                false);
  }

  /**
   * Sets a given {@link Node} to non-null in the given {@code store}. Calls to this method
   * implement case 2.
   *
   * @param store the store to update
   * @param node the node that should be non-null
   */
  protected void makeNonNull(NullnessStore store, Node node) {
    JavaExpression internalRepr = JavaExpression.fromNode(node);
    store.insertValue(internalRepr, NONNULL);
  }

  /** Sets a given {@link Node} {@code node} to non-null in the given {@link TransferResult}. */
  protected void makeNonNull(TransferResult<NullnessValue, NullnessStore> result, Node node) {
    if (result.containsTwoStores()) {
      makeNonNull(result.getThenStore(), node);
      makeNonNull(result.getElseStore(), node);
    } else {
      makeNonNull(result.getRegularStore(), node);
    }
  }

  /** Refine the given result to @NonNull. */
  protected void refineToNonNull(TransferResult<NullnessValue, NullnessStore> result) {
    NullnessValue oldResultValue = result.getResultValue();
    NullnessValue refinedResultValue =
        analysis.createSingleAnnotationValue(NONNULL, oldResultValue.getUnderlyingType());
    NullnessValue newResultValue = refinedResultValue.mostSpecific(oldResultValue, null);
    result.setResultValue(newResultValue);
  }

  @Override
  protected @Nullable NullnessValue finishValue(
      @Nullable NullnessValue value, NullnessStore store) {
    value = super.finishValue(value, store);
    if (value != null) {
      value.isPolyNullNonNull = store.isPolyNullNonNull();
      value.isPolyNullNull = store.isPolyNullNull();
    }
    return value;
  }

  @Override
  protected @Nullable NullnessValue finishValue(
      @Nullable NullnessValue value, NullnessStore thenStore, NullnessStore elseStore) {
    value = super.finishValue(value, thenStore, elseStore);
    if (value != null) {
      value.isPolyNullNonNull = thenStore.isPolyNullNonNull() && elseStore.isPolyNullNonNull();
      value.isPolyNullNull = thenStore.isPolyNullNull() && elseStore.isPolyNullNull();
    }
    return value;
  }

  /**
   * {@inheritDoc}
   *
   * <p>Furthermore, this method refines the type to {@code NonNull} for the appropriate branch if
   * an expression is compared to the {@code null} literal (listed as case 1 in the class
   * description).
   */
  @Override
  protected TransferResult<NullnessValue, NullnessStore> strengthenAnnotationOfEqualTo(
      TransferResult<NullnessValue, NullnessStore> res,
      Node firstNode,
      Node secondNode,
      NullnessValue firstValue,
      NullnessValue secondValue,
      boolean notEqualTo) {
    res =
        super.strengthenAnnotationOfEqualTo(
            res, firstNode, secondNode, firstValue, secondValue, notEqualTo);
    if (firstNode instanceof NullLiteralNode) {
      NullnessStore thenStore = res.getThenStore();
      NullnessStore elseStore = res.getElseStore();

      List<Node> secondParts = splitAssignments(secondNode);
      for (Node secondPart : secondParts) {
        JavaExpression secondInternal = JavaExpression.fromNode(secondPart);
        if (CFAbstractStore.canInsertJavaExpression(secondInternal)) {
          thenStore = thenStore == null ? res.getThenStore() : thenStore;
          elseStore = elseStore == null ? res.getElseStore() : elseStore;
          if (notEqualTo) {
            thenStore.insertValue(secondInternal, NONNULL);
          } else {
            elseStore.insertValue(secondInternal, NONNULL);
          }
        }
      }

      Set<AnnotationMirror> secondAnnos =
          secondValue != null
              ? secondValue.getAnnotations()
              : AnnotationUtils.createAnnotationSet();
      if (nullnessTypeFactory.containsSameByClass(secondAnnos, PolyNull.class)) {
        thenStore = thenStore == null ? res.getThenStore() : thenStore;
        elseStore = elseStore == null ? res.getElseStore() : elseStore;
        // TODO: methodTree is null for lambdas.  Handle that case.  See Issue3850.java.
        MethodTree methodTree = analysis.getContainingMethod(secondNode.getTree());
        ExecutableElement methodElem =
            methodTree == null ? null : TreeUtils.elementFromDeclaration(methodTree);
        if (notEqualTo) {
          elseStore.setPolyNullNull(true);
          if (methodElem != null && polyNullIsNonNull(methodElem, thenStore)) {
            thenStore.setPolyNullNonNull(true);
          }
        } else {
          thenStore.setPolyNullNull(true);
          if (methodElem != null && polyNullIsNonNull(methodElem, elseStore)) {
            elseStore.setPolyNullNonNull(true);
          }
        }
      }

      if (thenStore != null) {
        return new ConditionalTransferResult<>(res.getResultValue(), thenStore, elseStore);
      }
    }
    return res;
  }

  /**
   * Returns true if every formal parameter that is declared as @PolyNull is currently known to be
   * non-null.
   *
   * @param method a method
   * @param s a store
   * @return true if every formal parameter declared as @PolyNull is non-null
   */
  private boolean polyNullIsNonNull(ExecutableElement method, NullnessStore s) {
    // No need to check the receiver, which is always non-null.
    for (VariableElement var : method.getParameters()) {
      AnnotatedTypeMirror varType = atypeFactory.fromElement(var);

      if (containsPolyNullNotAtTopLevel(varType)) {
        return false;
      }

      if (varType.hasAnnotation(POLYNULL)) {
        NullnessValue v = s.getValue(new LocalVariable(var));
        if (!AnnotationUtils.containsSameByName(v.getAnnotations(), NONNULL)) {
          return false;
        }
      }
    }
    return true;
  }

  /**
   * A scanner that returns true if there is an occurrence of @PolyNull that is not at the top
   * level.
   */
  // Not static so it can access field POLYNULL.
  private class ContainsPolyNullNotAtTopLevelScanner
      extends SimpleAnnotatedTypeScanner<Boolean, Void> {
    /**
     * True if the top-level type has not yet been processed (by the first call to defaultAction).
     */
    private boolean isTopLevel = true;

    /** Create a ContainsPolyNullNotAtTopLevelScanner. */
    ContainsPolyNullNotAtTopLevelScanner() {
      super(Boolean::logicalOr, false);
    }

    @Override
    protected Boolean defaultAction(AnnotatedTypeMirror type, Void p) {
      if (isTopLevel) {
        isTopLevel = false;
        return false;
      } else {
        return type.hasAnnotation(POLYNULL);
      }
    }
  }

  /**
   * Returns true if there is an occurrence of @PolyNull that is not at the top level.
   *
   * @param t a type
   * @return true if there is an occurrence of @PolyNull that is not at the top level
   */
  private boolean containsPolyNullNotAtTopLevel(AnnotatedTypeMirror t) {
    return new ContainsPolyNullNotAtTopLevelScanner().visit(t);
  }

  @Override
  public TransferResult<NullnessValue, NullnessStore> visitArrayAccess(
      ArrayAccessNode n, TransferInput<NullnessValue, NullnessStore> p) {
    TransferResult<NullnessValue, NullnessStore> result = super.visitArrayAccess(n, p);
    makeNonNull(result, n.getArray());
    return result;
  }

  @Override
  public TransferResult<NullnessValue, NullnessStore> visitInstanceOf(
      InstanceOfNode n, TransferInput<NullnessValue, NullnessStore> p) {
    TransferResult<NullnessValue, NullnessStore> result = super.visitInstanceOf(n, p);
    NullnessStore thenStore = result.getThenStore();
    NullnessStore elseStore = result.getElseStore();
    makeNonNull(thenStore, n.getOperand());
    return new ConditionalTransferResult<>(result.getResultValue(), thenStore, elseStore);
  }

  @Override
  public TransferResult<NullnessValue, NullnessStore> visitMethodAccess(
      MethodAccessNode n, TransferInput<NullnessValue, NullnessStore> p) {
    TransferResult<NullnessValue, NullnessStore> result = super.visitMethodAccess(n, p);
    makeNonNull(result, n.getReceiver());
    return result;
  }

  @Override
  public TransferResult<NullnessValue, NullnessStore> visitFieldAccess(
      FieldAccessNode n, TransferInput<NullnessValue, NullnessStore> p) {
    TransferResult<NullnessValue, NullnessStore> result = super.visitFieldAccess(n, p);
    makeNonNull(result, n.getReceiver());
    return result;
  }

  @Override
  public TransferResult<NullnessValue, NullnessStore> visitThrow(
      ThrowNode n, TransferInput<NullnessValue, NullnessStore> p) {
    TransferResult<NullnessValue, NullnessStore> result = super.visitThrow(n, p);
    makeNonNull(result, n.getExpression());
    return result;
  }

  /*
   * Provided that m is of a type that implements interface java.util.Map:
   * <ul>
   * <li>Given a call m.get(k), if k is @KeyFor("m") and m's value type is @NonNull,
   *     then the result is @NonNull in the thenStore and elseStore of the transfer result.
   * </ul>
   */
  @Override
  public TransferResult<NullnessValue, NullnessStore> visitMethodInvocation(
      MethodInvocationNode n, TransferInput<NullnessValue, NullnessStore> in) {
    TransferResult<NullnessValue, NullnessStore> result = super.visitMethodInvocation(n, in);

    // Make receiver non-null.
    Node receiver = n.getTarget().getReceiver();
    makeNonNull(result, receiver);

    // For all formal parameters with a non-null annotation, make the actual argument non-null.
    // The point of this is to prevent cascaded errors -- the Nullness Checker will issue a
    // warning for the method invocation, but not for subsequent uses of the argument.  See test
    // case FlowNullness.java.
    MethodInvocationTree tree = n.getTree();
    ExecutableElement method = TreeUtils.elementFromUse(tree);
    AnnotatedExecutableType methodType = nullnessTypeFactory.getAnnotatedType(method);
    List<AnnotatedTypeMirror> methodParams = methodType.getParameterTypes();
    List<? extends ExpressionTree> methodArgs = tree.getArguments();
    for (int i = 0; i < methodParams.size() && i < methodArgs.size(); ++i) {
      if (methodParams.get(i).hasAnnotation(NONNULL)) {
        makeNonNull(result, n.getArgument(i));
      }
    }

    // Refine result to @NonNull if n is an invocation of Map.get, the argument is a key for
    // the map, and the map's value type is not @Nullable.
    if (keyForTypeFactory != null && keyForTypeFactory.isMapGet(n)) {
      String mapName = JavaExpression.fromNode(receiver).toString();
      AnnotatedTypeMirror receiverType = nullnessTypeFactory.getReceiverType(n.getTree());

      if (keyForTypeFactory.isKeyForMap(mapName, methodArgs.get(0))
          && !hasNullableValueType(receiverType)) {
        makeNonNull(result, n);
        refineToNonNull(result);
      }
    }

    return result;
  }

  /**
   * Returns true if mapType's value type (the V type argument to Map) is @Nullable.
   *
   * @param mapOrSubtype the Map type, or a subtype
   * @return true if mapType's value type is @Nullable
   */
  private boolean hasNullableValueType(AnnotatedTypeMirror mapOrSubtype) {
    AnnotatedDeclaredType mapType =
        AnnotatedTypes.asSuper(nullnessTypeFactory, mapOrSubtype, MAP_TYPE);
    int numTypeArguments = mapType.getTypeArguments().size();
    if (numTypeArguments != 2) {
      throw new BugInCF("Wrong number %d of type arguments: %s", numTypeArguments, mapType);
    }
    AnnotatedTypeMirror valueType = mapType.getTypeArguments().get(1);
    return valueType.hasAnnotation(NULLABLE);
  }

  @Override
  public TransferResult<NullnessValue, NullnessStore> visitReturn(
      ReturnNode n, TransferInput<NullnessValue, NullnessStore> in) {
    TransferResult<NullnessValue, NullnessStore> result = super.visitReturn(n, in);

    if (result.getResultValue() == null) {
      // Make sure there is a value for return statements, to record (at this return
      // statement) the values of isPolyNullNotNull and isPolyNullNull.
      return recreateTransferResult(createDummyValue(), result);
    } else {
      return result;
    }
  }

  /** Creates a dummy abstract value (whose type is not supposed to be looked at). */
  private NullnessValue createDummyValue() {
    TypeMirror dummy = analysis.getEnv().getTypeUtils().getPrimitiveType(TypeKind.BOOLEAN);
    Set<AnnotationMirror> annos = AnnotationUtils.createAnnotationSet();
    annos.addAll(nullnessTypeFactory.getQualifierHierarchy().getBottomAnnotations());
    return new NullnessValue(analysis, annos, dummy);
  }
}
