package org.checkerframework.javacutil;

import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
import com.sun.tools.javac.api.JavacScope;
import com.sun.tools.javac.code.Kinds;
import com.sun.tools.javac.code.Kinds.KindSelector;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.DeferredAttr;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.comp.Resolve;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Names;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;

/** A utility class to find symbols corresponding to string references (identifiers). */
// This class reflectively accesses jdk.compiler/com.sun.tools.javac.comp.
// This is why --add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED is required when
// running the Checker Framework.  If this class is re-written, then that --add-opens should be
// removed.
public class Resolver {
  private final Resolve resolve;
  private final Names names;
  private final Trees trees;
  private final Log log;

  private static final Method FIND_METHOD;
  private static final Method FIND_VAR;
  private static final Method FIND_IDENT;
  private static final Method FIND_IDENT_IN_TYPE;
  private static final Method FIND_IDENT_IN_PACKAGE;
  private static final Method FIND_TYPE;

  private static final Class<?> ACCESSERROR;
  // Note that currently access(...) is defined in InvalidSymbolError, a superclass of AccessError
  private static final Method ACCESSERROR_ACCESS;

  static {
    try {
      FIND_METHOD =
          Resolve.class.getDeclaredMethod(
              "findMethod",
              Env.class,
              Type.class,
              Name.class,
              List.class,
              List.class,
              boolean.class,
              boolean.class);
      FIND_METHOD.setAccessible(true);

      FIND_VAR = Resolve.class.getDeclaredMethod("findVar", Env.class, Name.class);
      FIND_VAR.setAccessible(true);

      FIND_IDENT =
          Resolve.class.getDeclaredMethod("findIdent", Env.class, Name.class, KindSelector.class);
      FIND_IDENT.setAccessible(true);

      FIND_IDENT_IN_TYPE =
          Resolve.class.getDeclaredMethod(
              "findIdentInType", Env.class, Type.class, Name.class, KindSelector.class);
      FIND_IDENT_IN_TYPE.setAccessible(true);

      FIND_IDENT_IN_PACKAGE =
          Resolve.class.getDeclaredMethod(
              "findIdentInPackage", Env.class, TypeSymbol.class, Name.class, KindSelector.class);
      FIND_IDENT_IN_PACKAGE.setAccessible(true);

      FIND_TYPE = Resolve.class.getDeclaredMethod("findType", Env.class, Name.class);
      FIND_TYPE.setAccessible(true);
    } catch (Exception e) {
      Error err =
          new AssertionError("Compiler 'Resolve' class doesn't contain required 'find' method");
      err.initCause(e);
      throw err;
    }

    try {
      ACCESSERROR = Class.forName("com.sun.tools.javac.comp.Resolve$AccessError");
      ACCESSERROR_ACCESS = ACCESSERROR.getMethod("access", Name.class, TypeSymbol.class);
      ACCESSERROR_ACCESS.setAccessible(true);
    } catch (ClassNotFoundException e) {
      throw new BugInCF("Compiler 'Resolve$AccessError' class could not be retrieved.", e);
    } catch (NoSuchMethodException e) {
      throw new BugInCF(
          "Compiler 'Resolve$AccessError' class doesn't contain required 'access' method", e);
    }
  }

  public Resolver(ProcessingEnvironment env) {
    Context context = ((JavacProcessingEnvironment) env).getContext();
    this.resolve = Resolve.instance(context);
    this.names = Names.instance(context);
    this.trees = Trees.instance(env);
    this.log = Log.instance(context);
  }

  /**
   * Determine the environment for the given path.
   *
   * @param path the tree path to the local scope
   * @return the corresponding attribution environment
   */
  public Env<AttrContext> getEnvForPath(TreePath path) {
    TreePath iter = path;
    JavacScope scope = null;
    while (scope == null && iter != null) {
      try {
        scope = (JavacScope) trees.getScope(iter);
      } catch (Throwable t) {
        // Work around Issue #1059 by skipping through the TreePath until something
        // doesn't crash. This probably returns the class scope, so users might not
        // get the variables they expect. But that is better than crashing.
        iter = iter.getParentPath();
      }
    }
    if (scope != null) {
      return scope.getEnv();
    } else {
      throw new BugInCF("Could not determine any possible scope for path: " + path.getLeaf());
    }
  }

  /**
   * Finds the package with name {@code name}.
   *
   * @param name the name of the package
   * @param path the tree path to the local scope
   * @return the {@code PackageSymbol} for the package if it is found, {@code null} otherwise
   */
  public @Nullable PackageSymbol findPackage(String name, TreePath path) {
    Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
    try {
      Env<AttrContext> env = getEnvForPath(path);
      Element res =
          wrapInvocationOnResolveInstance(
              FIND_IDENT, env, names.fromString(name), Kinds.KindSelector.PCK);
      // findIdent will return a PackageSymbol even for a symbol that is not a package, such as
      // a.b.c.MyClass.myStaticField. "exists()" must be called on it to ensure that it exists.
      if (res.getKind() == ElementKind.PACKAGE) {
        PackageSymbol ps = (PackageSymbol) res;
        return ps.exists() ? ps : null;
      } else {
        return null;
      }
    } finally {
      log.popDiagnosticHandler(discardDiagnosticHandler);
    }
  }

  /**
   * Finds the field with name {@code name} in {@code type} or a superclass or superinterface of
   * {@code type}.
   *
   * <p>The method adheres to all the rules of Java's scoping (while also considering the imports)
   * for name resolution.
   *
   * @param name the name of the field
   * @param type the type of the receiver (i.e., the type in which to look for the field)
   * @param path the tree path to the local scope
   * @return the element for the field, {@code null} otherwise
   */
  public @Nullable VariableElement findField(String name, TypeMirror type, TreePath path) {
    Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
    try {
      Env<AttrContext> env = getEnvForPath(path);
      Element res =
          wrapInvocationOnResolveInstance(
              FIND_IDENT_IN_TYPE, env, type, names.fromString(name), Kinds.KindSelector.VAR);

      if (res.getKind().isField()) {
        return (VariableElement) res;
      } else if (res.getKind() == ElementKind.OTHER && ACCESSERROR.isInstance(res)) {
        // Return the inaccessible field that was found
        return (VariableElement) wrapInvocation(res, ACCESSERROR_ACCESS, null, null);
      } else {
        // Most likely didn't find the field and the Element is a SymbolNotFoundError
        return null;
      }
    } finally {
      log.popDiagnosticHandler(discardDiagnosticHandler);
    }
  }

  /**
   * Finds the local variable (including formal parameters) with name {@code name} in the given
   * scope.
   *
   * @param name the name of the local variable
   * @param path the tree path to the local scope
   * @return the element for the local variable, {@code null} otherwise
   */
  public @Nullable VariableElement findLocalVariableOrParameter(String name, TreePath path) {
    Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
    try {
      Env<AttrContext> env = getEnvForPath(path);
      Element res = wrapInvocationOnResolveInstance(FIND_VAR, env, names.fromString(name));
      if (res.getKind() == ElementKind.LOCAL_VARIABLE || res.getKind() == ElementKind.PARAMETER) {
        return (VariableElement) res;
      } else {
        // The Element might be FIELD or a SymbolNotFoundError.
        return null;
      }
    } finally {
      log.popDiagnosticHandler(discardDiagnosticHandler);
    }
  }

  /**
   * Finds the class literal with name {@code name}.
   *
   * <p>The method adheres to all the rules of Java's scoping (while also considering the imports)
   * for name resolution.
   *
   * @param name the name of the class
   * @param path the tree path to the local scope
   * @return the element for the class
   */
  public Element findClass(String name, TreePath path) {
    Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
    try {
      Env<AttrContext> env = getEnvForPath(path);
      return wrapInvocationOnResolveInstance(FIND_TYPE, env, names.fromString(name));
    } finally {
      log.popDiagnosticHandler(discardDiagnosticHandler);
    }
  }

  /**
   * Finds the class with name {@code name} in a given package.
   *
   * @param name the name of the class
   * @param pck the PackageSymbol for the package
   * @param path the tree path to the local scope
   * @return the {@code ClassSymbol} for the class if it is found, {@code null} otherwise
   */
  public @Nullable ClassSymbol findClassInPackage(String name, PackageSymbol pck, TreePath path) {
    Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
    try {
      Env<AttrContext> env = getEnvForPath(path);
      Element res =
          wrapInvocationOnResolveInstance(
              FIND_IDENT_IN_PACKAGE, env, pck, names.fromString(name), Kinds.KindSelector.TYP);
      if (ElementUtils.isTypeElement(res)) {
        return (ClassSymbol) res;
      } else {
        return null;
      }
    } finally {
      log.popDiagnosticHandler(discardDiagnosticHandler);
    }
  }

  /**
   * Finds the method element for a given name and list of expected parameter types.
   *
   * <p>The method adheres to all the rules of Java's scoping (while also considering the imports)
   * for name resolution.
   *
   * <p>(This method takes into account autoboxing.)
   *
   * @param methodName name of the method to find
   * @param receiverType type of the receiver of the method
   * @param path tree path
   * @param argumentTypes types of arguments passed to the method call
   * @return the method element (if found)
   */
  public @Nullable ExecutableElement findMethod(
      String methodName,
      TypeMirror receiverType,
      TreePath path,
      java.util.List<TypeMirror> argumentTypes) {
    Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
    try {
      Env<AttrContext> env = getEnvForPath(path);

      Type site = (Type) receiverType;
      Name name = names.fromString(methodName);
      List<Type> argtypes = List.nil();
      for (TypeMirror a : argumentTypes) {
        argtypes = argtypes.append((Type) a);
      }
      List<Type> typeargtypes = List.nil();
      boolean allowBoxing = true;
      boolean useVarargs = false;

      try {
        // For some reason we have to set our own method context, which is rather ugly.
        // TODO: find a nicer way to do this.
        Object methodContext = buildMethodContext();
        Object oldContext = getField(resolve, "currentResolutionContext");
        setField(resolve, "currentResolutionContext", methodContext);
        Element result =
            wrapInvocationOnResolveInstance(
                FIND_METHOD, env, site, name, argtypes, typeargtypes, allowBoxing, useVarargs);
        setField(resolve, "currentResolutionContext", oldContext);
        if (result.getKind() == ElementKind.METHOD || result.getKind() == ElementKind.CONSTRUCTOR) {
          return (ExecutableElement) result;
        }
        return null;
      } catch (Throwable t) {
        Error err =
            new AssertionError(
                String.format(
                    "Unexpected reflection error in findMethod(%s, %s, ..., %s)",
                    methodName,
                    receiverType,
                    // path
                    argumentTypes));
        err.initCause(t);
        throw err;
      }
    } finally {
      log.popDiagnosticHandler(discardDiagnosticHandler);
    }
  }

  /** Build an instance of {@code Resolve$MethodResolutionContext}. */
  protected Object buildMethodContext()
      throws ClassNotFoundException, InstantiationException, IllegalAccessException,
          InvocationTargetException, NoSuchFieldException {
    // Class is not accessible, instantiate reflectively.
    Class<?> methCtxClss =
        Class.forName("com.sun.tools.javac.comp.Resolve$MethodResolutionContext");
    Constructor<?> constructor = methCtxClss.getDeclaredConstructors()[0];
    constructor.setAccessible(true);
    Object methodContext = constructor.newInstance(resolve);
    // we need to also initialize the fields attrMode and step
    setField(methodContext, "attrMode", DeferredAttr.AttrMode.CHECK);
    @SuppressWarnings("rawtypes")
    List<?> phases = (List) getField(resolve, "methodResolutionSteps");
    assert phases != null : "@AssumeAssertion(nullness): assumption";
    setField(methodContext, "step", phases.get(1));
    return methodContext;
  }

  /**
   * Reflectively set a field.
   *
   * @param receiver the receiver in which to set the field
   * @param fieldName name of field to set
   * @param value new value for field
   * @throws NoSuchFieldException if the field does not exist in the receiver
   * @throws IllegalAccessException if the field is not accessible
   */
  @SuppressWarnings({
    "nullness:argument",
    "interning:argument"
  }) // assume that the fields all accept null and uninterned values
  private void setField(Object receiver, String fieldName, @Nullable Object value)
      throws NoSuchFieldException, IllegalAccessException {
    Field f = receiver.getClass().getDeclaredField(fieldName);
    f.setAccessible(true);
    f.set(receiver, value);
  }

  /** Reflectively get the value of a field. */
  private @Nullable Object getField(Object receiver, String fieldName)
      throws NoSuchFieldException, IllegalAccessException {
    Field f = receiver.getClass().getDeclaredField(fieldName);
    f.setAccessible(true);
    return f.get(receiver);
  }

  /**
   * Wrap a method invocation on the {@code resolve} object.
   *
   * @param method the method to called
   * @param args the arguments to the call
   * @return the result of invoking the method on {@code resolve} (as the receiver) and the
   *     arguments
   */
  private Symbol wrapInvocationOnResolveInstance(Method method, Object... args) {
    return wrapInvocation(resolve, method, args);
  }

  /**
   * Invoke a method reflectively.
   *
   * @param receiver the receiver
   * @param method the method to called
   * @param args the arguments to the call
   * @return the result of invoking the method on the receiver and arguments
   */
  private Symbol wrapInvocation(Object receiver, Method method, @Nullable Object... args) {
    try {
      @SuppressWarnings("nullness") // assume arguments are OK
      @NonNull Symbol res = (Symbol) method.invoke(receiver, args);
      return res;
    } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
      throw new BugInCF(
          e,
          "Unexpected reflection error in wrapInvocation(%s, %s, %s)",
          receiver,
          method,
          Arrays.toString(args));
    }
  }
}
