package org.checkerframework.javacutil;

import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.CapturedType;
import com.sun.tools.javac.code.Type.ClassType;
import com.sun.tools.javac.code.TypeTag;
import com.sun.tools.javac.model.JavacTypes;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.util.Context;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.Name;
import javax.lang.model.element.NestingKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.UnionType;
import javax.lang.model.type.WildcardType;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.signature.qual.BinaryName;
import org.checkerframework.checker.signature.qual.CanonicalNameOrEmpty;
import org.checkerframework.checker.signature.qual.DotSeparatedIdentifiers;
import org.checkerframework.checker.signature.qual.FullyQualifiedName;
import org.plumelib.util.CollectionsPlume;
import org.plumelib.util.ImmutableTypes;

/**
 * A utility class that helps with {@link TypeMirror}s. It complements {@link Types}, providing
 * methods that {@link Types} does not.
 */
public final class TypesUtils {

  /** Class cannot be instantiated. */
  private TypesUtils() {
    throw new AssertionError("Class TypesUtils cannot be instantiated.");
  }

  /// Creating types

  /**
   * Returns the {@link TypeMirror} for a given {@link Class}.
   *
   * @param clazz a class
   * @param types the type utilities
   * @param elements the element utiliites
   * @return the TypeMirror for {@code clazz}
   */
  public static TypeMirror typeFromClass(Class<?> clazz, Types types, Elements elements) {
    if (clazz == void.class) {
      return types.getNoType(TypeKind.VOID);
    } else if (clazz.isPrimitive()) {
      String primitiveName = clazz.getName().toUpperCase();
      TypeKind primitiveKind = TypeKind.valueOf(primitiveName);
      return types.getPrimitiveType(primitiveKind);
    } else if (clazz.isArray()) {
      TypeMirror componentType = typeFromClass(clazz.getComponentType(), types, elements);
      return types.getArrayType(componentType);
    } else {
      String name = clazz.getCanonicalName();
      assert name != null : "@AssumeAssertion(nullness): assumption";
      TypeElement element = elements.getTypeElement(name);
      if (element == null) {
        throw new BugInCF("Unrecognized class: " + clazz);
      }
      return element.asType();
    }
  }

  /**
   * Returns an {@link ArrayType} with elements of type {@code componentType}.
   *
   * @param componentType the component type of the created array type
   * @param types the type utilities
   * @return an {@link ArrayType} whose elements have type {@code componentType}
   */
  public static ArrayType createArrayType(TypeMirror componentType, Types types) {
    JavacTypes t = (JavacTypes) types;
    return t.getArrayType(componentType);
  }

  /// Creating a Class<?>

  /**
   * Returns the {@link Class} for a given {@link TypeMirror}. Returns {@code Object.class} if it
   * cannot determine anything more specific.
   *
   * @param typeMirror a TypeMirror
   * @return the class for {@code typeMirror}
   */
  public static Class<?> getClassFromType(TypeMirror typeMirror) {

    switch (typeMirror.getKind()) {
      case INT:
        return int.class;
      case LONG:
        return long.class;
      case SHORT:
        return short.class;
      case BYTE:
        return byte.class;
      case CHAR:
        return char.class;
      case DOUBLE:
        return double.class;
      case FLOAT:
        return float.class;
      case BOOLEAN:
        return boolean.class;

      case ARRAY:
        Class<?> componentClass = getClassFromType(((ArrayType) typeMirror).getComponentType());
        // In Java 12, use this instead:
        // return fooClass.arrayType();
        return java.lang.reflect.Array.newInstance(componentClass, 0).getClass();

      case DECLARED:
        // BUG: need to compute a @ClassGetName, but this code computes a
        // @CanonicalNameOrEmpty.  They are different for inner classes.
        @SuppressWarnings("signature") // https://tinyurl.com/cfissue/658 for Names.toString
        @DotSeparatedIdentifiers String typeString = TypesUtils.getQualifiedName((DeclaredType) typeMirror).toString();
        if (typeString.equals("<nulltype>")) {
          return void.class;
        }

        try {
          return Class.forName(typeString);
        } catch (ClassNotFoundException | UnsupportedClassVersionError e) {
          return Object.class;
        }

      default:
        return Object.class;
    }
  }

  /// Getters

  /**
   * Gets the fully qualified name for a provided type. It returns an empty name if type is an
   * anonymous type.
   *
   * @param type the declared type
   * @return the name corresponding to that type
   */
  @SuppressWarnings("signature:return") // todo: add fake override of Name.toString.
  public static @CanonicalNameOrEmpty String getQualifiedName(DeclaredType type) {
    TypeElement element = (TypeElement) type.asElement();
    @CanonicalNameOrEmpty Name name = element.getQualifiedName();
    return name.toString();
  }

  /**
   * Returns the simple type name, without annotations.
   *
   * @param type a type
   * @return the simple type name, without annotations
   */
  public static String simpleTypeName(TypeMirror type) {
    switch (type.getKind()) {
      case ARRAY:
        return simpleTypeName(((ArrayType) type).getComponentType()) + "[]";
      case TYPEVAR:
        return ((TypeVariable) type).asElement().getSimpleName().toString();
      case DECLARED:
        return ((DeclaredType) type).asElement().getSimpleName().toString();
      case NULL:
        return "<nulltype>";
      case VOID:
        return "void";
      case WILDCARD:
        WildcardType wildcard = (WildcardType) type;
        TypeMirror extendsBound = wildcard.getExtendsBound();
        TypeMirror superBound = wildcard.getSuperBound();
        return "?"
            + (extendsBound != null ? " extends " + simpleTypeName(extendsBound) : "")
            + (superBound != null ? " super " + simpleTypeName(superBound) : "");
      case UNION:
        StringJoiner sj = new StringJoiner(" | ");
        for (TypeMirror alternative : ((UnionType) type).getAlternatives()) {
          sj.add(simpleTypeName(alternative));
        }
        return sj.toString();
      default:
        if (type.getKind().isPrimitive()) {
          return TypeAnnotationUtils.unannotatedType(type).toString();
        } else {
          throw new BugInCF(
              "simpleTypeName: unhandled type kind: %s, type: %s", type.getKind(), type);
        }
    }
  }

  /**
   * Returns the binary name.
   *
   * @param type a type
   * @return the binary name
   */
  public static @BinaryName String binaryName(TypeMirror type) {
    if (type.getKind() != TypeKind.DECLARED) {
      throw new BugInCF("Only declared types have a binary name");
    }
    return ElementUtils.getBinaryName((TypeElement) ((DeclaredType) type).asElement());
  }

  /**
   * Returns the type element for {@code type} if {@code type} is a class, interface, annotation
   * type, or enum. Otherwise, returns null.
   *
   * @param type whose element is returned
   * @return the type element for {@code type} if {@code type} is a class, interface, annotation
   *     type, or enum; otherwise, returns {@code null}
   */
  public static @Nullable TypeElement getTypeElement(TypeMirror type) {
    Element element = ((Type) type).asElement();
    if (element == null) {
      return null;
    }
    if (ElementUtils.isTypeElement(element)) {
      return (TypeElement) element;
    }
    return null;
  }

  /**
   * Given an array type, returns the type with all array levels stripped off.
   *
   * @param at an array type
   * @return the type with all array levels stripped off
   */
  public static TypeMirror getInnermostComponentType(ArrayType at) {
    TypeMirror result = at;
    while (result.getKind() == TypeKind.ARRAY) {
      result = ((ArrayType) result).getComponentType();
    }
    return result;
  }

  /// Equality

  /**
   * Returns true iff the arguments are both the same declared types.
   *
   * <p>This is needed because class {@code Type.ClassType} does not override equals.
   *
   * @param t1 the first type to test
   * @param t2 the second type to test
   * @return whether the arguments are the same declared types
   */
  public static boolean areSameDeclaredTypes(Type.ClassType t1, Type.ClassType t2) {
    // Do a cheaper test first
    if (t1.tsym.name != t2.tsym.name) {
      return false;
    }
    return t1.toString().equals(t1.toString());
  }

  /**
   * Returns true iff the arguments are both the same primitive type.
   *
   * @param left a type
   * @param right a type
   * @return whether the arguments are the same primitive type
   */
  public static boolean areSamePrimitiveTypes(TypeMirror left, TypeMirror right) {
    if (!isPrimitive(left) || !isPrimitive(right)) {
      return false;
    }

    return (left.getKind() == right.getKind());
  }

  /// Predicates

  /**
   * Checks if the type represents a java.lang.Object declared type.
   *
   * @param type the type
   * @return true iff type represents java.lang.Object
   */
  public static boolean isObject(TypeMirror type) {
    return isDeclaredOfName(type, "java.lang.Object");
  }

  /**
   * Checks if the type represents the java.lang.Class declared type.
   *
   * @param type the type
   * @return true iff type represents java.lang.Class
   */
  public static boolean isClass(TypeMirror type) {
    return isDeclaredOfName(type, "java.lang.Class");
  }

  /**
   * Checks if the type represents a java.lang.String declared type.
   *
   * @param type the type
   * @return true iff type represents java.lang.String
   */
  public static boolean isString(TypeMirror type) {
    return isDeclaredOfName(type, "java.lang.String");
  }

  /**
   * Checks if the type represents a boolean type, that is either boolean (primitive type) or
   * java.lang.Boolean.
   *
   * @param type the type to test
   * @return true iff type represents a boolean type
   */
  public static boolean isBooleanType(TypeMirror type) {
    return isDeclaredOfName(type, "java.lang.Boolean") || type.getKind() == TypeKind.BOOLEAN;
  }

  /**
   * Check if the type represents a declared type of the given qualified name.
   *
   * @param type the type
   * @return type iff type represents a declared type of the qualified name
   */
  public static boolean isDeclaredOfName(TypeMirror type, CharSequence qualifiedName) {
    return type.getKind() == TypeKind.DECLARED
        && getQualifiedName((DeclaredType) type).contentEquals(qualifiedName);
  }

  public static boolean isBoxedPrimitive(TypeMirror type) {
    if (type.getKind() != TypeKind.DECLARED) {
      return false;
    }

    String qualifiedName = getQualifiedName((DeclaredType) type).toString();

    return (qualifiedName.equals("java.lang.Boolean")
        || qualifiedName.equals("java.lang.Byte")
        || qualifiedName.equals("java.lang.Character")
        || qualifiedName.equals("java.lang.Short")
        || qualifiedName.equals("java.lang.Integer")
        || qualifiedName.equals("java.lang.Long")
        || qualifiedName.equals("java.lang.Double")
        || qualifiedName.equals("java.lang.Float"));
  }

  /**
   * Return true if this is an immutable type in the JDK.
   *
   * <p>This does not use immutability annotations and always returns false for user-defined
   * classes.
   */
  public static boolean isImmutableTypeInJdk(TypeMirror type) {
    return isPrimitive(type)
        || (type.getKind() == TypeKind.DECLARED
            && ImmutableTypes.isImmutable(getQualifiedName((DeclaredType) type).toString()));
  }

  /**
   * Returns true if type represents a Throwable type (e.g. Exception, Error).
   *
   * @return true if type represents a Throwable type (e.g. Exception, Error)
   */
  public static boolean isThrowable(TypeMirror type) {
    while (type != null && type.getKind() == TypeKind.DECLARED) {
      DeclaredType dt = (DeclaredType) type;
      TypeElement elem = (TypeElement) dt.asElement();
      Name name = elem.getQualifiedName();
      if ("java.lang.Throwable".contentEquals(name)) {
        return true;
      }
      type = elem.getSuperclass();
    }
    return false;
  }

  /**
   * Returns true iff the argument is an anonymous type.
   *
   * @return whether the argument is an anonymous type
   */
  public static boolean isAnonymous(TypeMirror type) {
    return (type instanceof DeclaredType)
        && ((TypeElement) ((DeclaredType) type).asElement()).getNestingKind()
            == NestingKind.ANONYMOUS;
  }

  /**
   * Returns true iff the argument is a primitive type.
   *
   * @return whether the argument is a primitive type
   */
  public static boolean isPrimitive(TypeMirror type) {
    switch (type.getKind()) {
      case BOOLEAN:
      case BYTE:
      case CHAR:
      case DOUBLE:
      case FLOAT:
      case INT:
      case LONG:
      case SHORT:
        return true;
      default:
        return false;
    }
  }

  /**
   * Returns true iff the argument is a primitive type or a boxed primitive type.
   *
   * @param type a type
   * @return true if the argument is a primitive type or a boxed primitive type
   */
  public static boolean isPrimitiveOrBoxed(TypeMirror type) {
    switch (type.getKind()) {
      case BOOLEAN:
      case BYTE:
      case CHAR:
      case DOUBLE:
      case FLOAT:
      case INT:
      case LONG:
      case SHORT:
        return true;

      case DECLARED:
        String qualifiedName = getQualifiedName((DeclaredType) type).toString();
        return (qualifiedName.equals("java.lang.Boolean")
            || qualifiedName.equals("java.lang.Byte")
            || qualifiedName.equals("java.lang.Character")
            || qualifiedName.equals("java.lang.Short")
            || qualifiedName.equals("java.lang.Integer")
            || qualifiedName.equals("java.lang.Long")
            || qualifiedName.equals("java.lang.Double")
            || qualifiedName.equals("java.lang.Float"));

      default:
        return false;
    }
  }

  /**
   * Returns true iff the argument is a primitive numeric type.
   *
   * @param type a type
   * @return true if the argument is a primitive numeric type
   */
  public static boolean isNumeric(TypeMirror type) {
    return TypeKindUtils.isNumeric(type.getKind());
  }

  /** The fully-qualified names of the numeric boxed types. */
  static final Set<@FullyQualifiedName String> numericBoxedTypes =
      new HashSet<>(
          Arrays.asList(
              "java.lang.Byte",
              "java.lang.Character",
              "java.lang.Short",
              "java.lang.Integer",
              "java.lang.Long",
              "java.lang.Double",
              "java.lang.Float"));

  /**
   * Returns true iff the argument is a boxed numeric type.
   *
   * @param type a type
   * @return true if the argument is a boxed numeric type
   */
  public static boolean isNumericBoxed(TypeMirror type) {
    return type.getKind() == TypeKind.DECLARED
        && numericBoxedTypes.contains(getQualifiedName((DeclaredType) type).toString());
  }

  /**
   * Returns true iff the argument is an integral primitive type.
   *
   * @param type a type
   * @return whether the argument is an integral primitive type
   */
  public static boolean isIntegralPrimitive(TypeMirror type) {
    switch (type.getKind()) {
      case BYTE:
      case CHAR:
      case INT:
      case LONG:
      case SHORT:
        return true;
      default:
        return false;
    }
  }

  /**
   * Return true if the argument TypeMirror is a (possibly boxed) integral type.
   *
   * @param type the type to inspect
   * @return true if type is an integral type
   */
  public static boolean isIntegralPrimitiveOrBoxed(TypeMirror type) {
    TypeKind kind = TypeKindUtils.primitiveOrBoxedToTypeKind(type);
    return kind != null && TypeKindUtils.isIntegral(kind);
  }

  /**
   * Returns true if declaredType is a Class that is used to box primitive type (e.g.
   * declaredType=java.lang.Double and primitiveType=22.5d )
   *
   * @param declaredType a type that might be a boxed type
   * @param primitiveType a type that might be a primitive type
   * @return true if {@code declaredType} is a box of {@code primitiveType}
   */
  public static boolean isBoxOf(TypeMirror declaredType, TypeMirror primitiveType) {
    if (declaredType.getKind() != TypeKind.DECLARED) {
      return false;
    }

    final String qualifiedName = getQualifiedName((DeclaredType) declaredType).toString();
    switch (primitiveType.getKind()) {
      case BOOLEAN:
        return qualifiedName.equals("java.lang.Boolean");
      case BYTE:
        return qualifiedName.equals("java.lang.Byte");
      case CHAR:
        return qualifiedName.equals("java.lang.Character");
      case DOUBLE:
        return qualifiedName.equals("java.lang.Double");
      case FLOAT:
        return qualifiedName.equals("java.lang.Float");
      case INT:
        return qualifiedName.equals("java.lang.Integer");
      case LONG:
        return qualifiedName.equals("java.lang.Long");
      case SHORT:
        return qualifiedName.equals("java.lang.Short");

      default:
        return false;
    }
  }

  /**
   * Returns true iff the argument is a boxed floating point type.
   *
   * @param type type to test
   * @return whether the argument is a boxed floating point type
   */
  public static boolean isBoxedFloating(TypeMirror type) {
    if (type.getKind() != TypeKind.DECLARED) {
      return false;
    }

    String qualifiedName = getQualifiedName((DeclaredType) type).toString();
    return qualifiedName.equals("java.lang.Double") || qualifiedName.equals("java.lang.Float");
  }

  /**
   * Returns true iff the argument is a primitive floating point type.
   *
   * @param type type mirror
   * @return whether the argument is a primitive floating point type
   */
  public static boolean isFloatingPrimitive(TypeMirror type) {
    switch (type.getKind()) {
      case DOUBLE:
      case FLOAT:
        return true;
      default:
        return false;
    }
  }

  /**
   * Return true if the argument TypeMirror is a (possibly boxed) floating point type.
   *
   * @param type the type to inspect
   * @return true if type is a floating point type
   */
  public static boolean isFloatingPoint(TypeMirror type) {
    TypeKind kind = TypeKindUtils.primitiveOrBoxedToTypeKind(type);
    return kind != null && TypeKindUtils.isFloatingPoint(kind);
  }

  /**
   * Returns whether a TypeMirror represents a class type.
   *
   * @param type a type that might be a class type
   * @return true if {@code} is a class type
   */
  public static boolean isClassType(TypeMirror type) {
    return (type instanceof Type.ClassType);
  }

  /**
   * Returns true if {@code type} has an enclosing type.
   *
   * @param type type to checker
   * @return true if {@code type} has an enclosing type
   */
  public static boolean hasEnclosingType(TypeMirror type) {
    Type e = ((Type) type).getEnclosingType();
    return e.getKind() != TypeKind.NONE;
  }

  /**
   * Returns whether or not {@code type} is a functional interface type (as defined in JLS 9.8).
   *
   * @param type possible functional interface type
   * @param env ProcessingEnvironment
   * @return whether or not {@code type} is a functional interface type (as defined in JLS 9.8)
   */
  public static boolean isFunctionalInterface(TypeMirror type, ProcessingEnvironment env) {
    Context ctx = ((JavacProcessingEnvironment) env).getContext();
    com.sun.tools.javac.code.Types javacTypes = com.sun.tools.javac.code.Types.instance(ctx);
    return javacTypes.isFunctionalInterface((Type) type);
  }

  /// Type variables and wildcards

  /**
   * If the argument is a bounded TypeVariable or WildcardType, return its non-variable,
   * non-wildcard upper bound. Otherwise, return the type itself.
   *
   * @param type a type
   * @return the non-variable, non-wildcard upper bound of a type, if it has one, or itself if it
   *     has no bounds
   */
  public static TypeMirror upperBound(TypeMirror type) {
    do {
      if (type instanceof TypeVariable) {
        TypeVariable tvar = (TypeVariable) type;
        if (tvar.getUpperBound() != null) {
          type = tvar.getUpperBound();
        } else {
          break;
        }
      } else if (type instanceof WildcardType) {
        WildcardType wc = (WildcardType) type;
        if (wc.getExtendsBound() != null) {
          type = wc.getExtendsBound();
        } else {
          break;
        }
      } else {
        break;
      }
    } while (true);
    return type;
  }

  /**
   * Get the type parameter for this wildcard from the underlying type's bound field This field is
   * sometimes null, in that case this method will return null.
   *
   * @return the TypeParameterElement the wildcard is an argument to, {@code null} otherwise
   */
  public static @Nullable TypeParameterElement wildcardToTypeParam(
      final Type.WildcardType wildcard) {

    final Element typeParamElement;
    if (wildcard.bound != null) {
      typeParamElement = wildcard.bound.asElement();
    } else {
      typeParamElement = null;
    }

    return (TypeParameterElement) typeParamElement;
  }

  /**
   * Version of com.sun.tools.javac.code.Types.wildUpperBound(Type) that works with both jdk8
   * (called upperBound there) and jdk8u.
   */
  // TODO: contrast to upperBound.
  public static Type wildUpperBound(TypeMirror tm, ProcessingEnvironment env) {
    Type t = (Type) tm;
    if (t.hasTag(TypeTag.WILDCARD)) {
      Context context = ((JavacProcessingEnvironment) env).getContext();
      Type.WildcardType w = (Type.WildcardType) TypeAnnotationUtils.unannotatedType(t);
      if (w.isSuperBound()) { // returns true if w is unbound
        Symtab syms = Symtab.instance(context);
        // w.bound is null if the wildcard is from bytecode.
        return w.bound == null ? syms.objectType : w.bound.getUpperBound();
      } else {
        return wildUpperBound(w.type, env);
      }
    } else {
      return TypeAnnotationUtils.unannotatedType(t);
    }
  }

  /**
   * Version of com.sun.tools.javac.code.Types.wildLowerBound(Type) that works with both jdk8
   * (called upperBound there) and jdk8u.
   */
  public static Type wildLowerBound(TypeMirror tm, ProcessingEnvironment env) {
    Type t = (Type) tm;
    if (t.hasTag(TypeTag.WILDCARD)) {
      Context context = ((JavacProcessingEnvironment) env).getContext();
      Symtab syms = Symtab.instance(context);
      Type.WildcardType w = (Type.WildcardType) TypeAnnotationUtils.unannotatedType(t);
      return w.isExtendsBound() ? syms.botType : wildLowerBound(w.type, env);
    } else {
      return TypeAnnotationUtils.unannotatedType(t);
    }
  }

  /**
   * Given a bounded type (wildcard or typevar) get the concrete type of its upper bound. If the
   * bounded type extends other bounded types, this method will iterate through their bounds until a
   * class, interface, or intersection is found.
   *
   * @return a type that is not a wildcard or typevar, or {@code null} if this type is an unbounded
   *     wildcard
   */
  public static @Nullable TypeMirror findConcreteUpperBound(final TypeMirror boundedType) {
    TypeMirror effectiveUpper = boundedType;
    outerLoop:
    while (true) {
      switch (effectiveUpper.getKind()) {
        case WILDCARD:
          effectiveUpper = ((javax.lang.model.type.WildcardType) effectiveUpper).getExtendsBound();
          if (effectiveUpper == null) {
            return null;
          }
          break;

        case TYPEVAR:
          effectiveUpper = ((TypeVariable) effectiveUpper).getUpperBound();
          break;

        default:
          break outerLoop;
      }
    }
    return effectiveUpper;
  }

  /**
   * Returns true if the erased type of subtype is a subtype of the erased type of supertype.
   *
   * @param subtype possible subtype
   * @param supertype possible supertype
   * @param types a Types object
   * @return true if the erased type of subtype is a subtype of the erased type of supertype
   */
  public static boolean isErasedSubtype(TypeMirror subtype, TypeMirror supertype, Types types) {
    return types.isSubtype(types.erasure(subtype), types.erasure(supertype));
  }

  /** Returns whether a TypeVariable represents a captured type. */
  public static boolean isCaptured(TypeMirror typeVar) {
    if (typeVar.getKind() != TypeKind.TYPEVAR) {
      return false;
    }
    return ((Type.TypeVar) TypeAnnotationUtils.unannotatedType(typeVar)).isCaptured();
  }

  /** If typeVar is a captured wildcard, returns that wildcard; otherwise returns {@code null}. */
  public static @Nullable WildcardType getCapturedWildcard(TypeVariable typeVar) {
    if (isCaptured(typeVar)) {
      return ((CapturedType) TypeAnnotationUtils.unannotatedType(typeVar)).wildcard;
    }
    return null;
  }

  /// Least upper bound and greatest lower bound

  /**
   * Returns the least upper bound of two {@link TypeMirror}s, ignoring any annotations on the
   * types.
   *
   * <p>Wrapper around Types.lub to add special handling for null types, primitives, and wildcards.
   *
   * @param tm1 a {@link TypeMirror}
   * @param tm2 a {@link TypeMirror}
   * @param processingEnv the {@link ProcessingEnvironment} to use
   * @return the least upper bound of {@code tm1} and {@code tm2}
   */
  public static TypeMirror leastUpperBound(
      TypeMirror tm1, TypeMirror tm2, ProcessingEnvironment processingEnv) {
    Type t1 = TypeAnnotationUtils.unannotatedType(tm1);
    Type t2 = TypeAnnotationUtils.unannotatedType(tm2);
    // Handle the 'null' type manually (not done by types.lub).
    if (t1.getKind() == TypeKind.NULL) {
      return t2;
    }
    if (t2.getKind() == TypeKind.NULL) {
      return t1;
    }
    if (t1.getKind() == TypeKind.WILDCARD) {
      WildcardType wc1 = (WildcardType) t1;
      t1 = (Type) wc1.getExtendsBound();
      if (t1 == null) {
        // Implicit upper bound of java.lang.Object
        Elements elements = processingEnv.getElementUtils();
        return elements.getTypeElement("java.lang.Object").asType();
      }
    }
    if (t2.getKind() == TypeKind.WILDCARD) {
      WildcardType wc2 = (WildcardType) t2;
      t2 = (Type) wc2.getExtendsBound();
      if (t2 == null) {
        // Implicit upper bound of java.lang.Object
        Elements elements = processingEnv.getElementUtils();
        return elements.getTypeElement("java.lang.Object").asType();
      }
    }
    JavacProcessingEnvironment javacEnv = (JavacProcessingEnvironment) processingEnv;
    com.sun.tools.javac.code.Types types =
        com.sun.tools.javac.code.Types.instance(javacEnv.getContext());
    if (types.isSameType(t1, t2)) {
      // Special case if the two types are equal.
      return t1;
    }
    // Special case for primitives.
    if (isPrimitive(t1) || isPrimitive(t2)) {
      if (types.isAssignable(t1, t2)) {
        return t2;
      } else if (types.isAssignable(t2, t1)) {
        return t1;
      } else {
        Elements elements = processingEnv.getElementUtils();
        return elements.getTypeElement("java.lang.Object").asType();
      }
    }
    return types.lub(t1, t2);
  }

  /**
   * Returns the greatest lower bound of two {@link TypeMirror}s, ignoring any annotations on the
   * types.
   *
   * <p>Wrapper around Types.glb to add special handling for null types, primitives, and wildcards.
   *
   * @param tm1 a {@link TypeMirror}
   * @param tm2 a {@link TypeMirror}
   * @param processingEnv the {@link ProcessingEnvironment} to use
   * @return the greatest lower bound of {@code tm1} and {@code tm2}
   */
  public static TypeMirror greatestLowerBound(
      TypeMirror tm1, TypeMirror tm2, ProcessingEnvironment processingEnv) {
    Type t1 = TypeAnnotationUtils.unannotatedType(tm1);
    Type t2 = TypeAnnotationUtils.unannotatedType(tm2);
    JavacProcessingEnvironment javacEnv = (JavacProcessingEnvironment) processingEnv;
    com.sun.tools.javac.code.Types types =
        com.sun.tools.javac.code.Types.instance(javacEnv.getContext());
    if (types.isSameType(t1, t2)) {
      // Special case if the two types are equal.
      return t1;
    }
    // Handle the 'null' type manually.
    if (t1.getKind() == TypeKind.NULL) {
      return t1;
    }
    if (t2.getKind() == TypeKind.NULL) {
      return t2;
    }
    // Special case for primitives.
    if (isPrimitive(t1) || isPrimitive(t2)) {
      if (types.isAssignable(t1, t2)) {
        return t1;
      } else if (types.isAssignable(t2, t1)) {
        return t2;
      } else {
        // Javac types.glb returns TypeKind.Error when the GLB does
        // not exist, but we can't create one.  Use TypeKind.NONE
        // instead.
        return processingEnv.getTypeUtils().getNoType(TypeKind.NONE);
      }
    }
    if (t1.getKind() == TypeKind.WILDCARD) {
      return t2;
    }
    if (t2.getKind() == TypeKind.WILDCARD) {
      return t1;
    }

    // If neither type is a primitive type, null type, or wildcard
    // and if the types are not the same, use javac types.glb
    return types.glb(t1, t2);
  }

  /**
   * Returns the most specific type from the list, or null if none exists.
   *
   * @param typeMirrors a list of types
   * @param processingEnv the {@link ProcessingEnvironment} to use
   * @return the most specific of the types, or null if none exists
   */
  public static @Nullable TypeMirror mostSpecific(
      List<TypeMirror> typeMirrors, ProcessingEnvironment processingEnv) {
    if (typeMirrors.size() == 1) {
      return typeMirrors.get(0);
    } else {
      JavacProcessingEnvironment javacEnv = (JavacProcessingEnvironment) processingEnv;
      com.sun.tools.javac.code.Types types =
          com.sun.tools.javac.code.Types.instance(javacEnv.getContext());
      com.sun.tools.javac.util.List<Type> typeList = typeMirrorListToTypeList(typeMirrors);
      Type glb = types.glb(typeList);
      for (Type candidate : typeList) {
        if (types.isSameType(glb, candidate)) {
          return candidate;
        }
      }
      return null;
    }
  }

  /**
   * Given a list of TypeMirror, return a list of Type.
   *
   * @param typeMirrors a list of TypeMirrors
   * @return the argument, converted to a javac list
   */
  private static com.sun.tools.javac.util.List<Type> typeMirrorListToTypeList(
      List<TypeMirror> typeMirrors) {
    List<Type> typeList = CollectionsPlume.mapList(Type.class::cast, typeMirrors);
    return com.sun.tools.javac.util.List.from(typeList);
  }

  /// Substitutions

  /**
   * Returns the return type of a method, given the receiver of the method call.
   *
   * @param methodElement a method
   * @param substitutedReceiverType the receiver type, after substitution
   * @param env the environment
   * @return the return type of the method
   */
  public static TypeMirror substituteMethodReturnType(
      Element methodElement, TypeMirror substitutedReceiverType, ProcessingEnvironment env) {

    com.sun.tools.javac.code.Types types =
        com.sun.tools.javac.code.Types.instance(InternalUtils.getJavacContext(env));

    Type substitutedMethodType =
        types.memberType((Type) substitutedReceiverType, (Symbol) methodElement);
    return substitutedMethodType.getReturnType();
  }

  /**
   * Returns {@code type} as {@code superType} if {@code superType} is a super type of {@code type};
   * otherwise, null.
   *
   * @return {@code type} as {@code superType} if {@code superType} is a super type of {@code type};
   *     otherwise, null
   */
  public static TypeMirror asSuper(
      TypeMirror type, TypeMirror superType, ProcessingEnvironment env) {
    Context ctx = ((JavacProcessingEnvironment) env).getContext();
    com.sun.tools.javac.code.Types javacTypes = com.sun.tools.javac.code.Types.instance(ctx);
    return javacTypes.asSuper((Type) type, ((Type) superType).tsym);
  }

  /**
   * Returns the superclass of the given class. Returns null if there is not one.
   *
   * @param type a type
   * @param types type utilities
   * @return the superclass of the given class, or null
   */
  public static @Nullable TypeMirror getSuperclass(TypeMirror type, Types types) {
    List<? extends TypeMirror> superTypes = types.directSupertypes(type);
    for (TypeMirror t : superTypes) {
      // ignore interface types
      if (!(t instanceof ClassType)) {
        continue;
      }
      ClassType tt = (ClassType) t;
      if (!tt.isInterface()) {
        return t;
      }
    }
    return null;
  }

  /**
   * Returns the type of primitive conversion from {@code from} to {@code to}.
   *
   * @param from a primitive type
   * @param to a primitive type
   * @return the type of primitive conversion from {@code from} to {@code to}
   */
  public static TypeKindUtils.PrimitiveConversionKind getPrimitiveConversionKind(
      PrimitiveType from, PrimitiveType to) {
    return TypeKindUtils.getPrimitiveConversionKind(from.getKind(), to.getKind());
  }

  /**
   * Returns a new type mirror with the same type as {@code type} where all the type variables in
   * {@code typeVariables} have been substituted with the type arguments in {@code typeArgs}.
   *
   * <p>This is a wrapper around {@link com.sun.tools.javac.code.Types#subst(Type,
   * com.sun.tools.javac.util.List, com.sun.tools.javac.util.List)}.
   *
   * @param type type to do substitution in
   * @param typeVariables type variables that should be replaced with the type mirror at the same
   *     index of {@code typeArgs}
   * @param typeArgs type mirrors that should replace the type variable at the same index of {@code
   *     typeVariables}
   * @param env processing environment
   * @return a new type mirror with the same type as {@code type} where all the type variables in
   *     {@code typeVariables} have been substituted with the type arguments in {@code typeArgs}
   */
  public static TypeMirror substitute(
      TypeMirror type,
      List<? extends TypeMirror> typeVariables,
      List<? extends TypeMirror> typeArgs,
      ProcessingEnvironment env) {

    List<Type> newP = CollectionsPlume.mapList(Type.class::cast, typeVariables);

    List<Type> newT = CollectionsPlume.mapList(Type.class::cast, typeArgs);

    JavacProcessingEnvironment javacEnv = (JavacProcessingEnvironment) env;
    com.sun.tools.javac.code.Types types =
        com.sun.tools.javac.code.Types.instance(javacEnv.getContext());
    return types.subst(
        (Type) type,
        com.sun.tools.javac.util.List.from(newP),
        com.sun.tools.javac.util.List.from(newT));
  }

  /**
   * Returns the depth of an array type.
   *
   * @param arrayType an array type
   * @return the depth of {@code arrayType}
   */
  public static int getArrayDepth(TypeMirror arrayType) {
    int counter = 0;
    TypeMirror type = arrayType;
    while (type.getKind() == TypeKind.ARRAY) {
      counter++;
      type = ((ArrayType) type).getComponentType();
    }
    return counter;
  }
}
