package org.checkerframework.javacutil;

import java.util.HashSet;
import java.util.Set;

import javax.annotation.processing.*;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;

import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.comp.CompileStates.CompileState;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;

import com.sun.source.tree.ClassTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;

/**
 * This class is an abstract annotation processor designed to be a
 * convenient superclass for concrete "type processors", processors that
 * require the type information in the processed source.
 *
 * <p>Type processing occurs in one round after the tool (e.g. Java compiler)
 * analyzes the source (all sources taken as input to the tool and sources
 * generated by other annotation processors).
 *
 * <p>The tool infrastructure will interact with classes extending this abstract
 * class as follows.
 *
 * <p>
 *  1-3 are Identical to the {@link Processor} life cycle.
 *  4-5 are unique to {@code AbstractTypeProcessor} subclasses.
 *
 * <ol>
 *
 * <li>If an existing {@code Processor} object is not being used, to
 * create an instance of a processor the tool calls the no-arg
 * constructor of the processor class.
 *
 * <li>Next, the tool calls the {@link #init init} method with
 * an appropriate {@code ProcessingEnvironment}.
 *
 * <li>Afterwards, the tool calls {@link #getSupportedAnnotationTypes
 * getSupportedAnnotationTypes}, {@link #getSupportedOptions
 * getSupportedOptions}, and {@link #getSupportedSourceVersion
 * getSupportedSourceVersion}.  These methods are only called once per
 * run, not on each round.
 *
 *
 * <li>For each class containing a supported annotation, the tool calls
 * {@link #typeProcess(TypeElement, TreePath) typeProcess} method on the
 * {@code Processor}.  The class is guaranteed to be type-checked Java code
 * and all the tree type and symbol information is resolved.
 *
 * <li>Finally, the tools calls the
 * {@link #typeProcessingOver() typeProcessingOver} method
 * on the {@code Processor}.
 *
 * </ol>
 *
 * <p>The tool is permitted to ask type processors to process a class once
 * it is analyzed before the rest of classes are analyzed.  The tool is also
 * permitted to stop type processing immediately if any errors are raised,
 * without invoking {@code typeProcessingOver}
 *
 * <p>A subclass may override any of the methods in this class, as long as the
 * general {@link javax.annotation.processing.Processor Processor}
 * contract is obeyed, with one notable exception.
 * {@link #process(Set, RoundEnvironment)} may not be overridden, as it
 * is called during the declaration annotation phase before classes are analyzed.
 *
 * @author Mahmood Ali
 * @author Werner Dietl
 */
public abstract class AbstractTypeProcessor extends AbstractProcessor {
    /**
     * The set of fully-qualified element names that should be type-checked.
     * We store the names of the elements, in order to prevent
     * possible confusion between different Element instantiations.
     */
    private final Set<Name> elements = new HashSet<Name>();

    /**
     * Method {@link #typeProcessingStart()} must be invoked exactly once,
     * before any invocation of {@link #typeProcess(TypeElement, TreePath)}.
     */
    private boolean hasInvokedTypeProcessingStart = false;

    /**
     * Method {@link #typeProcessingOver()} must be invoked exactly once,
     * after the last invocation of {@link #typeProcess(TypeElement, TreePath)}.
     */
    private static boolean hasInvokedTypeProcessingOver = false;

    /**
     * The TaskListener registered for completion of attribution.
     */
    private final AttributionTaskListener listener = new AttributionTaskListener();

    /**
     * Constructor for subclasses to call.
     */
    protected AbstractTypeProcessor() { }

    /**
     * {@inheritDoc}
     *
     * Register a TaskListener that will get called after FLOW.
     */
    @Override
    public void init(ProcessingEnvironment env) {
        super.init(env);
        JavacTask.instance(env).addTaskListener(listener);
        Context ctx = ((JavacProcessingEnvironment) processingEnv).getContext();
        JavaCompiler compiler = JavaCompiler.instance(ctx);
        compiler.shouldStopPolicyIfNoError = CompileState.max(compiler.shouldStopPolicyIfNoError,
                                                           CompileState.FLOW);
    }

    /**
     * The use of this method is obsolete in type processors.  The method is
     * called during declaration annotation processing phase only.
     * It registers the names of elements to process.
     */
    @Override
    public final boolean process(Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnv) {
        for (TypeElement elem : ElementFilter.typesIn(roundEnv.getRootElements())) {
            elements.add(elem.getQualifiedName());
        }
        return false;
    }

    /**
     * A method to be called once before the first call to typeProcess.
     *
     * <p>Subclasses may override this method to do any initialization work.
     */
    public void typeProcessingStart() {}

    /**
     * Processes a fully-analyzed class that contains a supported annotation
     * (see {@link #getSupportedAnnotationTypes()}).
     *
     * <p>The passed class is always valid type-checked Java code.
     *
     * @param element       element of the analyzed class
     * @param tree  the tree path to the element, with the leaf being a
     *              {@link ClassTree}
     */
    public abstract void typeProcess(TypeElement element, TreePath tree);

    /**
     * A method to be called once all the classes are processed and no error
     * is reported.
     *
     * <p>Subclasses may override this method to do any aggregate analysis
     * (e.g. generate report, persistence) or resource deallocation.
     *
     * <p>If an error (a Java error or a processor error) is reported, this
     * method is not guaranteed to be invoked.
     */
    public void typeProcessingOver() { }

    /**
     * A task listener that invokes the processor whenever a class is fully
     * analyzed.
     */
    private final class AttributionTaskListener implements TaskListener {

        @Override
        public void finished(TaskEvent e) {
            if (e.getKind() != TaskEvent.Kind.ANALYZE) {
                return;
            }

            if (!hasInvokedTypeProcessingStart) {
                typeProcessingStart();
                hasInvokedTypeProcessingStart = true;
            }

            Log log = Log.instance(((JavacProcessingEnvironment) processingEnv).getContext());

            if (!hasInvokedTypeProcessingOver && elements.isEmpty() && log.nerrors == 0) {
                typeProcessingOver();
                hasInvokedTypeProcessingOver = true;
            }

            if (e.getTypeElement() == null) {
                throw new AssertionError("event task without a type element");
            }
            if (e.getCompilationUnit() == null) {
                throw new AssertionError("event task without compilation unit");
            }

            if (!elements.remove(e.getTypeElement().getQualifiedName())) {
                return;
            }

            TypeElement elem = e.getTypeElement();
            TreePath p = Trees.instance(processingEnv).getPath(elem);

            typeProcess(elem, p);

            if (!hasInvokedTypeProcessingOver && elements.isEmpty() && log.nerrors == 0) {
                typeProcessingOver();
                hasInvokedTypeProcessingOver = true;
            }
        }

        @Override
        public void started(TaskEvent e) { }
    }
}
