package org.checkerframework.javacutil;

import com.sun.source.tree.BlockTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompoundAssignmentTree;
import com.sun.source.tree.ConditionalExpressionTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreePath;
import java.util.EnumSet;
import java.util.Set;
import java.util.StringJoiner;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * Utility methods for obtaining or analyzing a javac {@code TreePath}.
 *
 * @see TreeUtils
 */
public final class TreePathUtil {

  /** Do not instantiate; this class is a collection of static methods. */
  private TreePathUtil() {
    throw new Error("Class TreeUtils cannot be instantiated.");
  }

  ///
  /// Retrieving a path
  ///

  /**
   * Gets path to the first (innermost) enclosing tree of the specified kind.
   *
   * @param path the path defining the tree node
   * @param kind the kind of the desired tree
   * @return the path to the enclosing tree of the given type, {@code null} otherwise
   */
  public static @Nullable TreePath pathTillOfKind(final TreePath path, final Tree.Kind kind) {
    return pathTillOfKind(path, EnumSet.of(kind));
  }

  /**
   * Gets path to the first (innermost) enclosing tree with any one of the specified kinds.
   *
   * @param path the path defining the tree node
   * @param kinds the set of kinds of the desired tree
   * @return the path to the enclosing tree of the given type, {@code null} otherwise
   */
  public static @Nullable TreePath pathTillOfKind(final TreePath path, final Set<Tree.Kind> kinds) {
    TreePath p = path;

    while (p != null) {
      Tree leaf = p.getLeaf();
      assert leaf != null;
      if (kinds.contains(leaf.getKind())) {
        return p;
      }
      p = p.getParentPath();
    }

    return null;
  }

  /**
   * Gets path to the first (innermost) enclosing class tree, where class is defined by the {@link
   * TreeUtils#classTreeKinds()} method.
   *
   * @param path the path defining the tree node
   * @return the path to the enclosing class tree, {@code null} otherwise
   */
  public static @Nullable TreePath pathTillClass(final TreePath path) {
    return pathTillOfKind(path, TreeUtils.classTreeKinds());
  }

  /**
   * Gets path to the first (innermost) enclosing method tree.
   *
   * @param path the path defining the tree node
   * @return the path to the enclosing class tree, {@code null} otherwise
   */
  public static @Nullable TreePath pathTillMethod(final TreePath path) {
    return pathTillOfKind(path, Tree.Kind.METHOD);
  }

  ///
  /// Retrieving a tree
  ///

  /**
   * Gets the first (innermost) enclosing tree in path, of the specified kind.
   *
   * @param path the path defining the tree node
   * @param kind the kind of the desired tree
   * @return the enclosing tree of the given type as given by the path, {@code null} otherwise
   */
  public static @Nullable Tree enclosingOfKind(final TreePath path, final Tree.Kind kind) {
    return enclosingOfKind(path, EnumSet.of(kind));
  }

  /**
   * Gets the first (innermost) enclosing tree in path, with any one of the specified kinds.
   *
   * @param path the path defining the tree node
   * @param kinds the set of kinds of the desired tree
   * @return the enclosing tree of the given type as given by the path, {@code null} otherwise
   */
  public static @Nullable Tree enclosingOfKind(final TreePath path, final Set<Tree.Kind> kinds) {
    TreePath p = pathTillOfKind(path, kinds);
    return (p == null) ? null : p.getLeaf();
  }

  /**
   * Gets the first (innermost) enclosing tree in path, of the specified class.
   *
   * @param <T> the type of {@code treeClass}
   * @param path the path defining the tree node
   * @param treeClass the class of the desired tree
   * @return the enclosing tree of the given type as given by the path, {@code null} otherwise
   */
  public static <T extends Tree> @Nullable T enclosingOfClass(
      final TreePath path, final Class<T> treeClass) {
    TreePath p = path;

    while (p != null) {
      Tree leaf = p.getLeaf();
      if (treeClass.isInstance(leaf)) {
        return treeClass.cast(leaf);
      }
      p = p.getParentPath();
    }

    return null;
  }

  /**
   * Gets the enclosing class of the tree node defined by the given {@link TreePath}. It returns a
   * {@link Tree}, from which {@code checkers.types.AnnotatedTypeMirror} or {@link Element} can be
   * obtained.
   *
   * @param path the path defining the tree node
   * @return the enclosing class (or interface) as given by the path, or {@code null} if one does
   *     not exist
   */
  public static @Nullable ClassTree enclosingClass(final TreePath path) {
    return (ClassTree) enclosingOfKind(path, TreeUtils.classTreeKinds());
  }

  /**
   * Gets the enclosing variable of a tree node defined by the given {@link TreePath}.
   *
   * @param path the path defining the tree node
   * @return the enclosing variable as given by the path, or {@code null} if one does not exist
   */
  public static @Nullable VariableTree enclosingVariable(final TreePath path) {
    return (VariableTree) enclosingOfKind(path, Tree.Kind.VARIABLE);
  }

  /**
   * Gets the enclosing method of the tree node defined by the given {@link TreePath}. It returns a
   * {@link Tree}, from which an {@code checkers.types.AnnotatedTypeMirror} or {@link Element} can
   * be obtained.
   *
   * <p>Also see {@code AnnotatedTypeFactory#getEnclosingMethod} and {@code
   * AnnotatedTypeFactory#getEnclosingClassOrMethod}, which do not require a TreePath.
   *
   * @param path the path defining the tree node
   * @return the enclosing method as given by the path, or {@code null} if one does not exist
   */
  public static @Nullable MethodTree enclosingMethod(final TreePath path) {
    return (MethodTree) enclosingOfKind(path, Tree.Kind.METHOD);
  }

  /**
   * Gets the enclosing method or lambda expression of the tree node defined by the given {@link
   * TreePath}. It returns a {@link Tree}, from which an {@code checkers.types.AnnotatedTypeMirror}
   * or {@link Element} can be obtained.
   *
   * @param path the path defining the tree node
   * @return the enclosing method or lambda as given by the path, or {@code null} if one does not
   *     exist
   */
  public static @Nullable Tree enclosingMethodOrLambda(final TreePath path) {
    return enclosingOfKind(path, EnumSet.of(Tree.Kind.METHOD, Kind.LAMBDA_EXPRESSION));
  }

  /**
   * Returns the top-level block that encloses the given path, or null if none does.
   *
   * @param path a path
   * @return the top-level block that encloses the given path, or null if none does
   */
  public static @Nullable BlockTree enclosingTopLevelBlock(TreePath path) {
    TreePath parentPath = path.getParentPath();
    while (parentPath != null
        && !TreeUtils.classTreeKinds().contains(parentPath.getLeaf().getKind())) {
      path = parentPath;
      parentPath = parentPath.getParentPath();
    }
    if (path.getLeaf().getKind() == Tree.Kind.BLOCK) {
      return (BlockTree) path.getLeaf();
    }
    return null;
  }

  /**
   * Gets the first (innermost) enclosing tree in path, that is not a parenthesis.
   *
   * @param path the path defining the tree node
   * @return a pair of a non-parenthesis tree that contains the argument, and its child that is the
   *     argument or is a parenthesized version of it
   */
  public static Pair<Tree, Tree> enclosingNonParen(final TreePath path) {
    TreePath parentPath = path.getParentPath();
    Tree enclosing = parentPath.getLeaf();
    Tree enclosingChild = path.getLeaf();
    while (enclosing.getKind() == Kind.PARENTHESIZED) {
      parentPath = parentPath.getParentPath();
      enclosingChild = enclosing;
      enclosing = parentPath.getLeaf();
    }
    return Pair.of(enclosing, enclosingChild);
  }

  /**
   * Returns the "assignment context" for the leaf of {@code treePath}, which is often the leaf of
   * the parent of {@code treePath}. (Does not handle pseudo-assignment of an argument to a
   * parameter or a receiver expression to a receiver.) This is not the same as {@code
   * org.checkerframework.dataflow.cfg.node.AssignmentContext}, which represents the left-hand side
   * rather than the assignment itself.
   *
   * <p>The assignment context for {@code treePath} is the leaf of its parent, if that leaf is one
   * of the following trees:
   *
   * <ul>
   *   <li>AssignmentTree
   *   <li>CompoundAssignmentTree
   *   <li>MethodInvocationTree
   *   <li>NewArrayTree
   *   <li>NewClassTree
   *   <li>ReturnTree
   *   <li>VariableTree
   * </ul>
   *
   * If the parent is a ConditionalExpressionTree we need to distinguish two cases: If the leaf is
   * either the then or else branch of the ConditionalExpressionTree, then recurse on the parent. If
   * the leaf is the condition of the ConditionalExpressionTree, then return null to not consider
   * this assignment context.
   *
   * <p>If the leaf is a ParenthesizedTree, then recurse on the parent.
   *
   * <p>Otherwise, null is returned.
   *
   * @param treePath a path
   * @return the assignment context as described, {@code null} otherwise
   */
  public static @Nullable Tree getAssignmentContext(final TreePath treePath) {
    TreePath parentPath = treePath.getParentPath();

    if (parentPath == null) {
      return null;
    }

    Tree parent = parentPath.getLeaf();
    switch (parent.getKind()) {
      case ASSIGNMENT: // See below for CompoundAssignmentTree.
      case METHOD_INVOCATION:
      case NEW_ARRAY:
      case NEW_CLASS:
      case RETURN:
      case VARIABLE:
        return parent;
      case CONDITIONAL_EXPRESSION:
        ConditionalExpressionTree cet = (ConditionalExpressionTree) parent;
        @SuppressWarnings("interning:not.interned") // AST node comparison
        boolean conditionIsLeaf = (cet.getCondition() == treePath.getLeaf());
        if (conditionIsLeaf) {
          // The assignment context for the condition is simply boolean.
          // No point in going on.
          return null;
        }
        // Otherwise use the context of the ConditionalExpressionTree.
        return getAssignmentContext(parentPath);
      case PARENTHESIZED:
        return getAssignmentContext(parentPath);
      default:
        // 11 Tree.Kinds are CompoundAssignmentTrees,
        // so use instanceof rather than listing all 11.
        if (parent instanceof CompoundAssignmentTree) {
          return parent;
        }
        return null;
    }
  }

  ///
  /// Predicates
  ///

  /**
   * Returns true if the tree is in a constructor or an initializer block.
   *
   * @param path the path to test
   * @return true if the path is in a constructor or an initializer block
   */
  public static boolean inConstructor(TreePath path) {
    MethodTree method = enclosingMethod(path);
    // If method is null, this is an initializer block.
    return method == null || TreeUtils.isConstructor(method);
  }

  /**
   * Returns true if the leaf of the tree path is in a static scope.
   *
   * @param path TreePath whose leaf may or may not be in static scope
   * @return true if the leaf of the tree path is in a static scope
   */
  public static boolean isTreeInStaticScope(TreePath path) {
    MethodTree enclosingMethod = enclosingMethod(path);

    if (enclosingMethod != null) {
      return enclosingMethod.getModifiers().getFlags().contains(Modifier.STATIC);
    }
    // no enclosing method, check for static or initializer block
    BlockTree block = enclosingTopLevelBlock(path);
    if (block != null) {
      return block.isStatic();
    }

    // check if its in a variable initializer
    Tree t = enclosingVariable(path);
    if (t != null) {
      return ((VariableTree) t).getModifiers().getFlags().contains(Modifier.STATIC);
    }
    ClassTree classTree = enclosingClass(path);
    if (classTree != null) {
      return classTree.getModifiers().getFlags().contains(Modifier.STATIC);
    }
    return false;
  }

  ///
  /// Formatting
  ///

  /**
   * Return a printed representation of a TreePath.
   *
   * @param path a TreePath
   * @return a printed representation of the given TreePath
   */
  public static String toString(TreePath path) {
    StringJoiner result = new StringJoiner(System.lineSeparator() + "    ");
    result.add("TreePath:");
    for (Tree t : path) {
      result.add(TreeUtils.toStringTruncated(t, 65) + " " + t.getKind());
    }
    return result.toString();
  }

  /**
   * Returns a string representation of the leaf of the given path, using {@link
   * TreeUtils#toStringTruncated}.
   *
   * @param path a path
   * @param length the maximum length for the result; must be at least 6
   * @return a one-line string representation of the leaf of the given path that is no longer than
   *     {@code length} characters long
   */
  public static String leafToStringTruncated(@Nullable TreePath path, int length) {
    if (path == null) {
      return "null";
    }
    return TreeUtils.toStringTruncated(path.getLeaf(), length);
  }
}
