package org.checkerframework.checker.index;

import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import java.util.List;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.ExecutableElement;
import org.checkerframework.checker.index.qual.LengthOf;
import org.checkerframework.dataflow.cfg.node.MethodAccessNode;
import org.checkerframework.dataflow.cfg.node.MethodInvocationNode;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.TreeUtils;

/**
 * Given a Tree or other construct, this class has methods to query whether it is a particular
 * method call.
 */
public class IndexMethodIdentifier {

  /** The {@code java.lang.Math#random()} method. */
  private final ExecutableElement mathRandom;
  /** The {@code java.util.Random#nextDouble()} method. */
  private final ExecutableElement randomNextDouble;
  /** The {@code java.util.Random#nextInt()} method. */
  private final ExecutableElement randomNextInt;
  /** The {@code java.lang.String#length()} method. */
  private final ExecutableElement stringLength;
  /** The {@code java.lang.Math#min()} methods. */
  private final List<ExecutableElement> mathMinMethods;
  /** The {@code java.lang.Math#max()} methods. */
  private final List<ExecutableElement> mathMaxMethods;

  /** The LengthOf.value argument/element. */
  private final ExecutableElement lengthOfValueElement;

  /** The type factory. */
  private final AnnotatedTypeFactory factory;

  public IndexMethodIdentifier(AnnotatedTypeFactory factory) {
    this.factory = factory;
    ProcessingEnvironment processingEnv = factory.getProcessingEnv();
    mathRandom = TreeUtils.getMethod("java.lang.Math", "random", 0, processingEnv);
    randomNextDouble = TreeUtils.getMethod("java.util.Random", "nextDouble", 0, processingEnv);
    randomNextInt = TreeUtils.getMethod("java.util.Random", "nextInt", 1, processingEnv);

    stringLength = TreeUtils.getMethod("java.lang.String", "length", 0, processingEnv);

    mathMinMethods = TreeUtils.getMethods("java.lang.Math", "min", 2, processingEnv);
    mathMaxMethods = TreeUtils.getMethods("java.lang.Math", "max", 2, processingEnv);

    lengthOfValueElement = TreeUtils.getMethod(LengthOf.class, "value", 0, processingEnv);
  }

  /** Returns true iff the argument is an invocation of Math.min. */
  public boolean isMathMin(Tree methodTree) {
    ProcessingEnvironment processingEnv = factory.getProcessingEnv();
    return TreeUtils.isMethodInvocation(methodTree, mathMinMethods, processingEnv);
  }

  /** Returns true iff the argument is an invocation of Math.max. */
  public boolean isMathMax(Tree methodTree) {
    ProcessingEnvironment processingEnv = factory.getProcessingEnv();
    return TreeUtils.isMethodInvocation(methodTree, mathMaxMethods, processingEnv);
  }

  /** Returns true iff the argument is an invocation of Math.random(). */
  public boolean isMathRandom(Tree tree, ProcessingEnvironment processingEnv) {
    return TreeUtils.isMethodInvocation(tree, mathRandom, processingEnv);
  }

  /** Returns true iff the argument is an invocation of Random.nextDouble(). */
  public boolean isRandomNextDouble(Tree tree, ProcessingEnvironment processingEnv) {
    return TreeUtils.isMethodInvocation(tree, randomNextDouble, processingEnv);
  }

  /** Returns true iff the argument is an invocation of Random.nextInt(). */
  public boolean isRandomNextInt(Tree tree, ProcessingEnvironment processingEnv) {
    return TreeUtils.isMethodInvocation(tree, randomNextInt, processingEnv);
  }

  /**
   * Returns true if {@code tree} is an invocation of a method that returns the length of "this"
   *
   * @param tree a tree
   * @return true if {@code tree} is an invocation of a method that returns the length of {@code
   *     this}
   */
  public boolean isLengthOfMethodInvocation(Tree tree) {
    if (tree.getKind() != Kind.METHOD_INVOCATION) {
      return false;
    }
    return isLengthOfMethodInvocation(TreeUtils.elementFromUse((MethodInvocationTree) tree));
  }

  /**
   * Returns true if {@code tree} evaluates to the length of "this". This might be a call to
   * String,length, or a method annotated with @LengthOf.
   *
   * @return true if {@code tree} evaluates to the length of "this"
   */
  public boolean isLengthOfMethodInvocation(ExecutableElement ele) {
    if (stringLength.equals(ele)) {
      // TODO: Why not just annotate String.length with @LengthOf and thus eliminate the
      // special case in this method's implementation?
      return true;
    }

    AnnotationMirror lengthOfAnno = factory.getDeclAnnotation(ele, LengthOf.class);
    if (lengthOfAnno == null) {
      return false;
    }
    AnnotationValue lengthOfValue = lengthOfAnno.getElementValues().get(lengthOfValueElement);
    return AnnotationUtils.annotationValueContains(lengthOfValue, "this");
  }

  /**
   * Returns true if {@code node} is an invocation of a method that returns the length of {@code
   * this}
   *
   * @param node a node
   * @return true if {@code node} is an invocation of a method that returns the length of {@code
   *     this}
   */
  public boolean isLengthOfMethodInvocation(Node node) {
    if (node instanceof MethodInvocationNode) {
      MethodInvocationNode methodInvocationNode = (MethodInvocationNode) node;
      MethodAccessNode methodAccessNode = methodInvocationNode.getTarget();
      ExecutableElement ele = methodAccessNode.getMethod();

      return isLengthOfMethodInvocation(ele);
    }
    return false;
  }
}
