/*
 * Copyright 2003-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.codehaus.groovy.classgen;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.expr.AnnotationConstantExpression;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.ListExpression;
import org.codehaus.groovy.ast.expr.PropertyExpression;
import org.codehaus.groovy.control.ErrorCollector;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
import org.codehaus.groovy.syntax.SyntaxException;


/**
 * An Annotation visitor responsible with:
 * - reading annotation metadata (@Retention, @Target, attribute types)
 * - verify that an <code>AnnotationNode</code> conforms to annotation meta
 * - enhancing an <code>AnnotationNode</code> AST to reflect real annotation meta
 * 
 * @author <a href='mailto:the[dot]mindstorm[at]gmail[dot]com'>Alex Popescu</a>
 */
public class AnnotationVisitor {
    private static final Class[] EMPTY_ARG_TYPES = new Class[0];
    private static final Object[] EMPTY_ARGS = new Object[0];
    
    private final Class annotationRootClass;
    private SourceUnit source;
    private ErrorCollector errorCollector;
    
    private AnnotationNode annotation;
    private Class annotationClass;
    private Map requiredAttrTypes = new HashMap(); // Map<String, Class>
    private Map defaultAttrTypes = new HashMap();  // Map<String, Class>
    
    public AnnotationVisitor(SourceUnit source, ErrorCollector errorCollector) {
        this.source = source;
        this.errorCollector = errorCollector;
        this.annotationRootClass = loadAnnotationRootClass();
    }
    
    public AnnotationNode visit(AnnotationNode node) {
        if(!isValidAnnotationClass(node)) {
            node.setValid(false);
            return node;
        }
        
        this.annotation = node;
        if(!node.getClassNode().isResolved()) {
            addError("Current type was not yet resolved. Cannot introspect it.");
            node.setValid(false);
            return node;
        }
        this.annotationClass = node.getClassNode().getTypeClass();
        
        extractAnnotationMeta(this.annotationClass);
        
        if(this.errorCollector.hasErrors()) {
            this.annotation.setValid(false);
            return this.annotation;
        }
        
        Map attributes = this.annotation.getMembers();
        for(Iterator it = attributes.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry entry = (Map.Entry) it.next();
            String attrName = (String) entry.getKey();
            Expression attrExpr = (Expression) entry.getValue();
            Class attrType = getAttributeType(attrName);
            if(attrType == null) {
                addError("Unknown attribute '" + attrName + "'", attrExpr);
                break;
            }
            visitExpression(attrName, attrExpr, attrType);
        }
        
        if(!this.requiredAttrTypes.isEmpty()) {
            addError("Required attributes " + this.requiredAttrTypes.keySet() + " not found",
                    this.annotation);
        }
        
        this.annotation.setValid(!this.errorCollector.hasErrors());
        return this.annotation;
    }
    
    /**
     * @param node
     * @return
     */
    private boolean isValidAnnotationClass(AnnotationNode node) {
        return node.getClassNode().implementsInterface("java.lang.annotation.Annotation");
    }

    protected void visitExpression(String attrName, Expression attrAst, Class attrType) {
        if(attrType.isArray()) {
            // check needed as @Test(attr = {"elem"}) passes through the parser
            if(attrAst instanceof ListExpression) {
                visitListExpression(attrName, (ListExpression) attrAst, attrType.getComponentType());
            }
            else {
                addError("Annotation list attributes must use Groovy notation [el1, el2]", attrAst);
            }
        }
        if(attrType.isPrimitive()) {
            visitConstantExpression(attrName, (ConstantExpression) attrAst, ClassHelper.getWrapper(ClassHelper.make(attrType)));
        }
        else if(String.class.equals(attrType)) {
            visitConstantExpression(attrName, (ConstantExpression) attrAst, ClassHelper.make(String.class));
        }
        else if(Class.class.equals(attrType)) {
            // there is nothing to check about ClassExpressions
        }
        else if(isEnum(attrType)) {
            visitEnumExpression(attrName, (PropertyExpression) attrAst, ClassHelper.make(attrType));
        }
        else if(isAnnotation(attrType)) {
            visitAnnotationExpression(attrName, (AnnotationConstantExpression) attrAst, attrType);
        }
    }
    
    /**
     * @param attrName
     * @param expression
     * @param attrType
     */
    protected void visitAnnotationExpression(String attrName, AnnotationConstantExpression expression, Class attrType) {
        AnnotationNode annotationNode = (AnnotationNode) expression.getValue();
        AnnotationVisitor visitor = new AnnotationVisitor(this.source, this.errorCollector);
        visitor.visit(annotationNode);
    }

    protected void visitListExpression(String attrName, ListExpression listExpr, Class elementType) {
        List expressions = listExpr.getExpressions();
        for (int i = 0; i < expressions.size(); i++) {
            visitExpression(attrName, (Expression) expressions.get(i), elementType);
        }
    }
    
    protected void visitConstantExpression(String attrName, ConstantExpression constExpr, ClassNode attrType) {
        if(!constExpr.getType().isDerivedFrom(attrType)) {
            addError("Attribute '" + attrName + "' should have type '" + attrType.getName() + "'; "
                    + "but found type '" + constExpr.getType().getName() + "'",
                    constExpr);
        }
    }
    
    protected void visitEnumExpression(String attrName, PropertyExpression propExpr, ClassNode attrType) {
        if(!propExpr.getObjectExpression().getType().isDerivedFrom(attrType)) {
            addError("Attribute '" + attrName + "' should have type '" + attrType.getName() +"' (Enum), but found "
                    + propExpr.getObjectExpression().getType().getName(), 
                    propExpr);
        }
    }
    
    private boolean isAnnotation(Class clazz) {
        Boolean result = (Boolean) invoke(clazz.getClass(), "isAnnotation", EMPTY_ARG_TYPES, clazz, EMPTY_ARGS);
        return result.booleanValue();
    }
    
    private boolean isEnum(Class clazz) {
        Boolean result = (Boolean) invoke(clazz.getClass(), "isEnum", EMPTY_ARG_TYPES, clazz, EMPTY_ARGS);
        return result.booleanValue();
    }
    
    private void extractAnnotationMeta(Class annotationClass) {
        initializeAnnotationMeta(annotationClass);
        initializeAttributeTypes(annotationClass);
    }
    
    private void initializeAnnotationMeta(Class annotationClass) {
        Object[] annotations = (Object[]) invoke(annotationClass.getClass(), 
                "getAnnotations", EMPTY_ARG_TYPES, annotationClass, EMPTY_ARGS);
        if (annotations == null) {
            addError("Cannot retrieve annotation meta information. " 
                    + ExtendedVerifier.JVM_ERROR_MESSAGE);
            return;
        }
        
        for(int i = 0; i < annotations.length; i++) {
            Class annotationType = (Class) invoke(this.annotationRootClass, 
                    "annotationType", EMPTY_ARG_TYPES, annotations[i], EMPTY_ARGS);
            if (annotationType == null) continue;
            
            if ("java.lang.annotation.Retention".equals(annotationType.getName())) {
                initializeRetention(annotationClass, annotationType, annotations[i]);
            }
            else if("java.lang.annotation.Target".equals(annotationType.getName())) {
                initializeTarget(annotationClass, annotationType, annotations[i]);
            }
        }
    }
    
    private void initializeAttributeTypes(Class annotationClass) {
        Method[] methods = annotationClass.getDeclaredMethods();
        for(int i = 0; i < methods.length; i++) {
            Object defaultValue = invoke(Method.class, "getDefaultValue", EMPTY_ARG_TYPES, methods[i], EMPTY_ARGS);
            if (defaultValue != null) { 
                // by now we know JDK1.5 API is available so a null means no default value
                defaultAttrTypes.put(methods[i].getName(), methods[i].getReturnType());
            }
            else {
                requiredAttrTypes.put(methods[i].getName(), methods[i].getReturnType());
            }
        }
    }
    
    private void initializeRetention(Class annotationClass, Class retentionClass, Object retentionAnnotation) {
        Object retentionPolicyEnum = 
            invoke(retentionClass, "value", EMPTY_ARG_TYPES, retentionAnnotation, EMPTY_ARGS);
        if (retentionPolicyEnum == null) {
            addError("Cannot read @RetentionPolicy on the @" + annotationClass.getName() 
                    + ExtendedVerifier.JVM_ERROR_MESSAGE);
            return;
        }
        
        if("RUNTIME".equals(retentionPolicyEnum.toString())) {
            this.annotation.setRuntimeRetention(true);
        }
        else if("SOURCE".equals(retentionPolicyEnum.toString())) {
            this.annotation.setSourceRetention(true);
        }
    }
    
    private void initializeTarget(Class annotationClass, Class targetClass, Object targetAnnotation) {
        Object[] elementTypeEnum =
            (Object[]) invoke(targetClass, "value", EMPTY_ARG_TYPES, targetAnnotation, EMPTY_ARGS);
        if (elementTypeEnum == null) {
            addError("Cannot read @Target on the @" + annotationClass.getName() 
                    + ExtendedVerifier.JVM_ERROR_MESSAGE);
            return;
        }
        int bitmap = 0;
        for (int i = 0; i < elementTypeEnum.length; i++) {
            String targetName = elementTypeEnum[i].toString();
            if("TYPE".equals(targetName)) {
                bitmap |= AnnotationNode.TYPE_TARGET;
            }
            else if("CONSTRUCTOR".equals(targetName)) {
                bitmap |= AnnotationNode.CONSTRUCTOR_TARGET;
            }
            else if("METHOD".equals(targetName)) {
                bitmap |= AnnotationNode.METHOD_TARGET;
            }
            else if("FIELD".equals(targetName)) {
                bitmap |= AnnotationNode.FIELD_TARGET;
            }
            else if("PARAMETER".equals(targetName)) {
                bitmap |= AnnotationNode.PARAMETER_TARGET;
            }
            else if("LOCAL_VARIABLE".equals(targetName)) {
                bitmap |= AnnotationNode.LOCAL_VARIABLE_TARGET;
            }
            else if("ANNOTATION".equals(targetName)) {
                bitmap |= AnnotationNode.ANNOTATION_TARGET;
            }
        }
        this.annotation.setAllowedTargets(bitmap);
    }
    
    protected void addError(String msg) {
        this.errorCollector.addErrorAndContinue(
          new SyntaxErrorMessage(new SyntaxException(msg 
                  + " in @" + this.annotationClass.getName() + '\n', 
                  this.annotation.getLineNumber(), 
                  this.annotation.getColumnNumber()), this.source)
        );
    }
    
    protected void addError(String msg, ASTNode expr) {
        this.errorCollector.addErrorAndContinue(
          new SyntaxErrorMessage(new SyntaxException(msg 
                  + " in @" + this.annotationClass.getName() + '\n', 
                  expr.getLineNumber(), 
                  expr.getColumnNumber()), this.source)
        );
    }
    
    private Class getAttributeType(String attr) {
        if(this.requiredAttrTypes.containsKey(attr)) {
            return (Class) this.requiredAttrTypes.remove(attr);
        }
        
        return (Class) this.defaultAttrTypes.remove(attr);
    }
    
    private Object invoke(Class clazz, String methodName, Class[] argTypes, Object target, Object[] args) {
        try {
            Method m = clazz.getMethod(methodName, argTypes);
            return m.invoke(target, args);
        }
        catch(Throwable cause) {
            // we report an error on called side
        }
     
        return null;
    }
    
    private Class loadAnnotationRootClass() {
        try {
            return Class.forName("java.lang.annotation.Annotation");
        }
        catch(Throwable cause) {
            // report the error later
        }
        
        return null;
    }
}
