package org.checkerframework.javacutil;

/*>>>
import org.checkerframework.checker.nullness.qual.Nullable;
*/

import static com.sun.tools.javac.code.Flags.ABSTRACT;
import static com.sun.tools.javac.code.Flags.EFFECTIVELY_FINAL;
import static com.sun.tools.javac.code.Flags.FINAL;

import com.sun.tools.javac.code.Symbol;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
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.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;

/** A Utility class for analyzing {@code Element}s. */
public class ElementUtils {

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

    /**
     * Returns the innermost type element enclosing the given element
     *
     * @param elem the enclosed element of a class
     * @return the innermost type element
     */
    public static TypeElement enclosingClass(final Element elem) {
        Element result = elem;
        while (result != null && !result.getKind().isClass() && !result.getKind().isInterface()) {
            /*@Nullable*/ Element encl = result.getEnclosingElement();
            result = encl;
        }
        return (TypeElement) result;
    }

    /**
     * Returns the innermost package element enclosing the given element. The same effect as {@link
     * javax.lang.model.util.Elements#getPackageOf(Element)}. Returns the element itself if it is a
     * package.
     *
     * @param elem the enclosed element of a package
     * @return the innermost package element
     */
    public static PackageElement enclosingPackage(final Element elem) {
        Element result = elem;
        while (result != null && result.getKind() != ElementKind.PACKAGE) {
            /*@Nullable*/ Element encl = result.getEnclosingElement();
            result = encl;
        }
        return (PackageElement) result;
    }

    /**
     * Returns the "parent" package element for the given package element. For package "A.B" it
     * gives "A". For package "A" it gives the default package. For the default package it returns
     * null;
     *
     * <p>Note that packages are not enclosed within each other, we have to manually climb the
     * namespaces. Calling "enclosingPackage" on a package element returns the package element
     * itself again.
     *
     * @param elem the package to start from
     * @return the parent package element
     */
    public static PackageElement parentPackage(final Elements e, final PackageElement elem) {
        // The following might do the same thing:
        //   ((Symbol) elt).owner;
        // TODO: verify and see whether the change is worth it.
        String fqnstart = elem.getQualifiedName().toString();
        String fqn = fqnstart;
        if (fqn != null && !fqn.isEmpty() && fqn.contains(".")) {
            fqn = fqn.substring(0, fqn.lastIndexOf('.'));
            return e.getPackageElement(fqn);
        }
        return null;
    }

    /**
     * Returns true if the element is a static element: whether it is a static field, static method,
     * or static class
     *
     * @return true if element is static
     */
    public static boolean isStatic(Element element) {
        return element.getModifiers().contains(Modifier.STATIC);
    }

    /**
     * Returns true if the element is a final element: a final field, final method, or final class
     *
     * @return true if the element is final
     */
    public static boolean isFinal(Element element) {
        return element.getModifiers().contains(Modifier.FINAL);
    }

    /**
     * Returns true if the element is a effectively final element.
     *
     * @return true if the element is effectively final
     */
    public static boolean isEffectivelyFinal(Element element) {
        Symbol sym = (Symbol) element;
        if (sym.getEnclosingElement().getKind() == ElementKind.METHOD
                && (sym.getEnclosingElement().flags() & ABSTRACT) != 0) {
            return true;
        }
        return (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0;
    }

    /**
     * Returns the {@code TypeMirror} for usage of Element as a value. It returns the return type of
     * a method element, the class type of a constructor, or simply the type mirror of the element
     * itself.
     *
     * @return the type for the element used as a value
     */
    public static TypeMirror getType(Element element) {
        if (element.getKind() == ElementKind.METHOD) {
            return ((ExecutableElement) element).getReturnType();
        } else if (element.getKind() == ElementKind.CONSTRUCTOR) {
            return enclosingClass(element).asType();
        } else {
            return element.asType();
        }
    }

    /**
     * Returns the qualified name of the inner most class enclosing the provided {@code Element}
     *
     * @param element an element enclosed by a class, or a {@code TypeElement}
     * @return the qualified {@code Name} of the innermost class enclosing the element
     */
    public static /*@Nullable*/ Name getQualifiedClassName(Element element) {
        if (element.getKind() == ElementKind.PACKAGE) {
            PackageElement elem = (PackageElement) element;
            return elem.getQualifiedName();
        }

        TypeElement elem = enclosingClass(element);
        if (elem == null) {
            return null;
        }

        return elem.getQualifiedName();
    }

    /** Returns a verbose name that identifies the element. */
    public static String getVerboseName(Element elt) {
        if (elt.getKind() == ElementKind.PACKAGE
                || elt.getKind().isClass()
                || elt.getKind().isInterface()) {
            return getQualifiedClassName(elt).toString();
        } else {
            return getQualifiedClassName(elt) + "." + elt.toString();
        }
    }

    /**
     * Check if the element is an element for 'java.lang.Object'
     *
     * @param element the type element
     * @return true iff the element is java.lang.Object element
     */
    public static boolean isObject(TypeElement element) {
        return element.getQualifiedName().contentEquals("java.lang.Object");
    }

    /** Returns true if the element is a constant time reference */
    public static boolean isCompileTimeConstant(Element elt) {
        return elt != null
                && (elt.getKind() == ElementKind.FIELD
                        || elt.getKind() == ElementKind.LOCAL_VARIABLE)
                && ((VariableElement) elt).getConstantValue() != null;
    }

    /**
     * Returns true if the element is declared in ByteCode. Always return false if elt is a package.
     */
    public static boolean isElementFromByteCode(Element elt) {
        if (elt == null) {
            return false;
        }

        if (elt instanceof Symbol.ClassSymbol) {
            Symbol.ClassSymbol clss = (Symbol.ClassSymbol) elt;
            if (null != clss.classfile) {
                // The class file could be a .java file
                return clss.classfile.getName().endsWith(".class");
            } else {
                return false;
            }
        }
        return isElementFromByteCode(elt.getEnclosingElement(), elt);
    }

    /**
     * Returns true if the element is declared in ByteCode. Always return false if elt is a package.
     */
    private static boolean isElementFromByteCode(Element elt, Element orig) {
        if (elt == null) {
            return false;
        }
        if (elt instanceof Symbol.ClassSymbol) {
            Symbol.ClassSymbol clss = (Symbol.ClassSymbol) elt;
            if (null != clss.classfile) {
                // The class file could be a .java file
                return (clss.classfile.getName().endsWith(".class")
                        || clss.classfile.getName().endsWith(".class)")
                        || clss.classfile.getName().endsWith(".class)]"));
            } else {
                return false;
            }
        }
        return isElementFromByteCode(elt.getEnclosingElement(), elt);
    }

    /** Returns the field of the class */
    public static VariableElement findFieldInType(TypeElement type, String name) {
        for (VariableElement field : ElementFilter.fieldsIn(type.getEnclosedElements())) {
            if (field.getSimpleName().toString().equals(name)) {
                return field;
            }
        }
        return null;
    }

    /**
     * Returns the elements of the fields whose simple names are {@code names} and are declared in
     * {@code type}.
     *
     * <p>If a field isn't declared in {@code type}, its element isn't included in the returned set.
     * If none of the fields is declared in {@code type}, the empty set is returned.
     *
     * @param type where to look for fields
     * @param names simple names of fields that might be declared in {@code type}
     * @return the elements of the fields whose simple names are {@code names} and are declared in
     *     {@code type}
     */
    public static Set<VariableElement> findFieldsInType(
            TypeElement type, Collection<String> names) {
        Set<VariableElement> results = new HashSet<VariableElement>();
        for (VariableElement field : ElementFilter.fieldsIn(type.getEnclosedElements())) {
            if (names.contains(field.getSimpleName().toString())) {
                results.add(field);
            }
        }
        return results;
    }

    /**
     * Returns non-private field elements, and side-effects {@code names} to remove them. For every
     * field name in {@code names} that is declared in {@code type} or a supertype, add its element
     * to the returned set and remove it from {@code names}.
     *
     * <p>When this routine returns, the combination of the return value and {@code names} has the
     * same cardinality, and represents the same fields, as {@code names} did when the method was
     * called.
     *
     * @param type where to look for fields
     * @param names simple names of fields that might be declared in {@code type} or a supertype.
     *     (Names that are found are removed from this list.)
     * @return the {@code VariableElement}s for non-private fields that are declared in {@code type}
     *     whose simple names were in {@code names} when the method was called.
     */
    public static Set<VariableElement> findFieldsInTypeOrSuperType(
            TypeMirror type, Collection<String> names) {
        Set<VariableElement> elements = new HashSet<>();
        findFieldsInTypeOrSuperType(type, names, elements);
        return elements;
    }

    /**
     * Side-effects both {@code foundFields} (which starts empty) and {@code notFound}, conceptually
     * moving elements from {@code notFound} to {@code foundFields}.
     */
    private static void findFieldsInTypeOrSuperType(
            TypeMirror type, Collection<String> notFound, Set<VariableElement> foundFields) {
        if (TypesUtils.isObject(type)) {
            return;
        }
        TypeElement elt = InternalUtils.getTypeElement(type);

        Set<VariableElement> fieldElts = findFieldsInType(elt, notFound);
        for (VariableElement field : new HashSet<>(fieldElts)) {
            if (!field.getModifiers().contains(Modifier.PRIVATE)) {
                notFound.remove(field.getSimpleName().toString());
            } else {
                fieldElts.remove(field);
            }
        }
        foundFields.addAll(fieldElts);

        if (!notFound.isEmpty()) {
            findFieldsInTypeOrSuperType(elt.getSuperclass(), notFound, foundFields);
        }
    }

    public static boolean isError(Element element) {
        return element.getClass()
                .getName()
                .equals("com.sun.tools.javac.comp.Resolve$SymbolNotFoundError");
    }

    /**
     * Does the given element need a receiver for accesses? For example, an access to a local
     * variable does not require a receiver.
     *
     * @param element the element to test
     * @return whether the element requires a receiver for accesses
     */
    public static boolean hasReceiver(Element element) {
        return (element.getKind().isField()
                        || element.getKind() == ElementKind.METHOD
                        || element.getKind() == ElementKind.CONSTRUCTOR)
                && !ElementUtils.isStatic(element);
    }

    /**
     * Determine all type elements for the classes and interfaces referenced (directly or
     * indirectly) in the extends/implements clauses of the given type element.
     *
     * <p>TODO: can we learn from the implementation of
     * com.sun.tools.javac.model.JavacElements.getAllMembers(TypeElement)?
     */
    public static List<TypeElement> getSuperTypes(Elements elements, TypeElement type) {

        List<TypeElement> superelems = new ArrayList<TypeElement>();
        if (type == null) {
            return superelems;
        }

        // Set up a stack containing type, which is our starting point.
        Deque<TypeElement> stack = new ArrayDeque<TypeElement>();
        stack.push(type);

        while (!stack.isEmpty()) {
            TypeElement current = stack.pop();

            // For each direct supertype of the current type element, if it
            // hasn't already been visited, push it onto the stack and
            // add it to our superelems set.
            TypeMirror supertypecls;
            try {
                supertypecls = current.getSuperclass();
            } catch (com.sun.tools.javac.code.Symbol.CompletionFailure cf) {
                // Looking up a supertype failed. This sometimes happens
                // when transitive dependencies are not on the classpath.
                // As javac didn't complain, let's also not complain.
                // TODO: Use an expanded ErrorReporter to output a message.
                supertypecls = null;
            }

            if (supertypecls != null && supertypecls.getKind() != TypeKind.NONE) {
                TypeElement supercls = (TypeElement) ((DeclaredType) supertypecls).asElement();
                if (!superelems.contains(supercls)) {
                    stack.push(supercls);
                    superelems.add(supercls);
                }
            }

            for (TypeMirror supertypeitf : current.getInterfaces()) {
                TypeElement superitf = (TypeElement) ((DeclaredType) supertypeitf).asElement();
                if (!superelems.contains(superitf)) {
                    stack.push(superitf);
                    superelems.add(superitf);
                }
            }
        }

        // Include java.lang.Object as implicit superclass for all classes and interfaces.
        TypeElement jlobject = elements.getTypeElement("java.lang.Object");
        if (!superelems.contains(jlobject)) {
            superelems.add(jlobject);
        }

        return Collections.<TypeElement>unmodifiableList(superelems);
    }

    /**
     * Return all fields declared in the given type or any superclass/interface. TODO: should this
     * use javax.lang.model.util.Elements.getAllMembers(TypeElement) instead of our own
     * getSuperTypes?
     */
    public static List<VariableElement> getAllFieldsIn(Elements elements, TypeElement type) {
        List<VariableElement> fields = new ArrayList<VariableElement>();
        fields.addAll(ElementFilter.fieldsIn(type.getEnclosedElements()));
        List<TypeElement> alltypes = getSuperTypes(elements, type);
        for (TypeElement atype : alltypes) {
            fields.addAll(ElementFilter.fieldsIn(atype.getEnclosedElements()));
        }
        return Collections.<VariableElement>unmodifiableList(fields);
    }

    /**
     * Return all methods declared in the given type or any superclass/interface. Note that no
     * constructors will be returned. TODO: should this use
     * javax.lang.model.util.Elements.getAllMembers(TypeElement) instead of our own getSuperTypes?
     */
    public static List<ExecutableElement> getAllMethodsIn(Elements elements, TypeElement type) {
        List<ExecutableElement> meths = new ArrayList<ExecutableElement>();
        meths.addAll(ElementFilter.methodsIn(type.getEnclosedElements()));

        List<TypeElement> alltypes = getSuperTypes(elements, type);
        for (TypeElement atype : alltypes) {
            meths.addAll(ElementFilter.methodsIn(atype.getEnclosedElements()));
        }
        return Collections.<ExecutableElement>unmodifiableList(meths);
    }

    public static boolean isTypeDeclaration(Element elt) {
        switch (elt.getKind()) {
                // These tree kinds are always declarations.  Uses of the declared
                // types have tree kind IDENTIFIER.
            case ANNOTATION_TYPE:
            case CLASS:
            case ENUM:
            case INTERFACE:
            case TYPE_PARAMETER:
                return true;

            default:
                return false;
        }
    }

    /**
     * Check that a method Element matches a signature.
     *
     * <p>Note: Matching the receiver type must be done elsewhere as the Element receiver type is
     * only populated when annotated.
     *
     * @param method the method Element
     * @param methodName the name of the method
     * @param parameters the formal parameters' Classes
     * @return true if the method matches
     */
    public static boolean matchesElement(
            ExecutableElement method, String methodName, Class<?>... parameters) {

        if (!method.getSimpleName().toString().equals(methodName)) {
            return false;
        }

        if (method.getParameters().size() != parameters.length) {
            return false;
        } else {
            for (int i = 0; i < method.getParameters().size(); i++) {
                if (!method.getParameters()
                        .get(i)
                        .asType()
                        .toString()
                        .equals(parameters[i].getName())) {

                    return false;
                }
            }
        }

        return true;
    }

    /** Returns true if the given element is, or overrides, method. */
    public static boolean isMethod(
            ExecutableElement questioned, ExecutableElement method, ProcessingEnvironment env) {
        TypeElement enclosing = (TypeElement) questioned.getEnclosingElement();
        return questioned.equals(method)
                || env.getElementUtils().overrides(questioned, method, enclosing);
    }
}
