/*
 * $Id:  $
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.struts.annotations.taglib.apt;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.TreeMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.declaration.AnnotationMirror;
import com.sun.mirror.declaration.AnnotationTypeDeclaration;
import com.sun.mirror.declaration.AnnotationTypeElementDeclaration;
import com.sun.mirror.declaration.AnnotationValue;
import com.sun.mirror.declaration.Declaration;
import com.sun.mirror.declaration.MethodDeclaration;
import com.sun.mirror.declaration.TypeDeclaration;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;

public class TagAnnotationProcessor implements AnnotationProcessor {
    public static final String TAG = "org.apache.struts2.views.annotations.StrutsTag";
    public static final String TAG_ATTRIBUTE = "org.apache.struts2.views.annotations.StrutsTagAttribute";
    public static final String TAG_SKIP_HIERARCHY = "org.apache.struts2.views.annotations.StrutsTagSkipInheritance";

    private AnnotationProcessorEnvironment environment;
    private AnnotationTypeDeclaration tagDeclaration;
    private AnnotationTypeDeclaration tagAttributeDeclaration;
    private AnnotationTypeDeclaration skipDeclaration;
    private Map<String, Tag> tags = new TreeMap<String, Tag>();

    public TagAnnotationProcessor(AnnotationProcessorEnvironment env) {
        environment = env;
        tagDeclaration = (AnnotationTypeDeclaration) environment
                .getTypeDeclaration(TAG);
        tagAttributeDeclaration = (AnnotationTypeDeclaration) environment
                .getTypeDeclaration(TAG_ATTRIBUTE);
        skipDeclaration = (AnnotationTypeDeclaration) environment
                .getTypeDeclaration(TAG_SKIP_HIERARCHY);
    }

    public void process() {
        // make sure all paramters were set
        checkOptions();

        // tags
        Collection<Declaration> tagDeclarations = environment
                .getDeclarationsAnnotatedWith(tagDeclaration);
        Collection<Declaration> attributesDeclarations = environment
                .getDeclarationsAnnotatedWith(tagAttributeDeclaration);
        Collection<Declaration> skipDeclarations = environment
                 .getDeclarationsAnnotatedWith(skipDeclaration);

        // find Tags
        for (Declaration declaration : tagDeclarations) {
            // type
            TypeDeclaration typeDeclaration = (TypeDeclaration) declaration;
            String typeName = typeDeclaration.getQualifiedName();
            Map<String, Object> values = getValues(typeDeclaration,
                    tagDeclaration);
            // create Tag and apply values found
            Tag tag = new Tag();
            tag.setDescription((String) values.get("description"));
            tag.setName((String) values.get("name"));
            tag.setTldBodyContent((String) values.get("tldBodyContent"));
            tag.setTldTagClass((String) values.get("tldTagClass"));
            tag.setDeclaredType(typeName);
	    tag.setAllowDynamicAttributes((Boolean) values.get("allowDynamicAttributes"));
            // add to map
            tags.put(typeName, tag);
        }
        
        //find attributes to be skipped
        for (Declaration declaration : skipDeclarations) {
            //types will be ignored when hierarchy is scanned
            if (declaration instanceof MethodDeclaration) {
                MethodDeclaration methodDeclaration = (MethodDeclaration) declaration;
                String typeName = methodDeclaration.getDeclaringType().getQualifiedName();
                String methodName = methodDeclaration.getSimpleName();
                String name = String.valueOf(Character.toLowerCase(methodName
                    .charAt(3)))
                    + methodName.substring(4);
                Tag tag = tags.get(typeName);
                if(tag != null) {
                    //if it is on an abstract class, there is not tag for it at this point
                    tags.get(typeName).addSkipAttribute(name);
                }
            }
        }

        // find Tags Attributes
        for (Declaration declaration : attributesDeclarations) {
            // type
            MethodDeclaration methodDeclaration = (MethodDeclaration) declaration;
            String typeName = methodDeclaration.getDeclaringType()
                    .getQualifiedName();
            Map<String, Object> values = getValues(methodDeclaration,
                    tagAttributeDeclaration);
            // create Attribute and apply values found
            TagAttribute attribute = new TagAttribute();
            String name = (String) values.get("name");
            if (name == null || name.length() == 0) {
                // get name from method
                String methodName = methodDeclaration.getSimpleName();
                name = String.valueOf(Character.toLowerCase(methodName
                        .charAt(3)))
                        + methodName.substring(4);
            }
            values.put("name", name);
            populateTagAttributes(attribute, values);
            // add to map
            Tag parentTag = tags.get(typeName);
            if (parentTag != null)
                tags.get(typeName).addTagAttribute(attribute);
            else {
                // an abstract or base class
                parentTag = new Tag();
                parentTag.setDeclaredType(typeName);
                parentTag.setInclude(false);
                parentTag.addTagAttribute(attribute);
                tags.put(typeName, parentTag);
            }
        }

        // we can't process the hierarchy on the first pass because
        // apt does not garantees that the base classes will be processed
        // before their subclasses
        for (Map.Entry<String, Tag> entry : tags.entrySet()) {
            processHierarchy(entry.getValue());
        }

        // save
        saveAsXml();
        saveTemplates();
    }

    private void populateTagAttributes(TagAttribute attribute, Map<String, Object> values) {
        attribute.setRequired((Boolean) values.get("required"));
        attribute.setRtexprvalue((Boolean) values.get("rtexprvalue"));
        attribute.setDefaultValue((String) values.get("defaultValue"));
        attribute.setType((String) values.get("type"));
        attribute.setDescription((String) values.get("description"));
        attribute.setName((String) values.get("name"));
    }

    private void processHierarchy(Tag tag) {
        try {
            Class clazz = Class.forName(tag.getDeclaredType());
            List<String> skipAttributes = tag.getSkipAttributes();
            //skip hierarchy processing if the class is marked with the skip annotation
            while(getAnnotation(TAG_SKIP_HIERARCHY, clazz.getAnnotations()) == null
                && ((clazz = clazz.getSuperclass()) != null)) {
                Tag parentTag = tags.get(clazz.getName());
                // copy parent annotations to this tag
                if(parentTag != null) {
                    for(TagAttribute attribute : parentTag.getAttributes()) {
                        if(!skipAttributes.contains(attribute.getName()))
                            tag.addTagAttribute(attribute);
                    }
                } else {
                    // Maybe the parent class is already compiled
                    addTagAttributesFromParent(tag, clazz);
                }
            }
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void addTagAttributesFromParent(Tag tag, Class clazz) throws ClassNotFoundException {
        try {
            BeanInfo info = Introspector.getBeanInfo(clazz);
            PropertyDescriptor[] props = info.getPropertyDescriptors();
            List<String> skipAttributes = tag.getSkipAttributes();
            
            //iterate over class fields
            for(int i = 0; i < props.length; ++i) {
                PropertyDescriptor prop = props[i];
                Method writeMethod = prop.getWriteMethod();
               
                //make sure it is public
                if(writeMethod != null && Modifier.isPublic(writeMethod.getModifiers())) {
                    //can't use the genertic getAnnotation 'cause the class it not on this jar
                    Annotation annotation = getAnnotation(TAG_ATTRIBUTE, writeMethod.getAnnotations());
                    if(annotation != null && !skipAttributes.contains(prop.getName())) {
                        Map<String, Object> values = getValues(annotation);
                        //create tag
                        TagAttribute attribute = new TagAttribute();
                        values.put("name", prop.getName());
                        populateTagAttributes(attribute, values);
                        tag.addTagAttribute(attribute);
                    }
                }

            }
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    private Annotation getAnnotation(String typeName, Annotation[] annotations) {
        for(int i = 0; i < annotations.length; i++) {
            if(annotations[i].annotationType().getName().equals(typeName))
                return annotations[i];
        }
        return null;
    }

    private void checkOptions() {
        if (getOption("tlibVersion") == null)
            throw new IllegalArgumentException("'tlibVersion' is missing");
        if (getOption("jspVersion") == null)
            throw new IllegalArgumentException("'jspVersion' is missing");
        if (getOption("shortName") == null)
            throw new IllegalArgumentException("'shortName' is missing");
        if (getOption("description") == null)
            throw new IllegalArgumentException("'description' is missing");
        if (getOption("displayName") == null)
            throw new IllegalArgumentException("'displayName' is missing");
        if (getOption("uri") == null)
            throw new IllegalArgumentException("'uri' is missing");
        if (getOption("outTemplatesDir") == null)
            throw new IllegalArgumentException("'outTemplatesDir' is missing");
        if (getOption("outFile") == null)
            throw new IllegalArgumentException("'outFile' is missing");
    }

    private void saveTemplates() {
        // freemarker configuration
        Configuration config = new Configuration();
        config.setClassForTemplateLoading(getClass(), "");
        config.setObjectWrapper(new DefaultObjectWrapper());

        try {
            // load template
            Template template = config.getTemplate("tag.ftl");
            String rootDir = (new File(getOption("outTemplatesDir")))
                    .getAbsolutePath();
            for (Tag tag : tags.values()) {
                if (tag.isInclude()) {
                    // model
                    HashMap<String, Tag> root = new HashMap<String, Tag>();
                    root.put("tag", tag);

                    // save file
                    BufferedWriter writer = new BufferedWriter(new FileWriter(
                            new File(rootDir, tag.getName() + ".html")));
                    try {
                        template.process(root, writer);
                    } finally {
                        writer.close();
                    }
                }
            }
        } catch (Exception e) {
            // oops we cannot throw checked exceptions
            throw new RuntimeException(e);
        }
    }

    private void saveAsXml() {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder;

        try {
            // create xml document
            builder = factory.newDocumentBuilder();
            Document document = builder.newDocument();
            document.setXmlVersion("1.0");

            // taglib
            Element tagLib = document.createElement("taglib");
            tagLib.setAttribute("xmlns", "http://java.sun.com/xml/ns/j2ee");
	    tagLib.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
	    tagLib.setAttribute("xsi:schemaLocation", "http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd");
	    tagLib.setAttribute("version", getOption("jspVersion"));
            document.appendChild(tagLib);
            // tag lib attributes
            appendTextNode(document, tagLib, "tlib-version",
                    getOption("tlibVersion"), false);
            appendTextNode(document, tagLib, "short-name",
                    getOption("shortName"), false);
            appendTextNode(document, tagLib, "uri", getOption("uri"), false);
            appendTextNode(document, tagLib, "display-name",
                    getOption("displayName"), false);
            appendTextNode(document, tagLib, "description",
                    getOption("description"), true);

            // create tags
            for (Map.Entry<String, Tag> entry : tags.entrySet()) {
                Tag tag = entry.getValue();
                if (tag.isInclude())
                    createElement(document, tagLib, tag);
            }

            // save to file
            TransformerFactory tf = TransformerFactory.newInstance();
            tf.setAttribute("indent-number", 2);
            Transformer transformer = tf.newTransformer();
            // if tiger would just format it :(
            // formatting bug in tiger
            // (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446)

            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

            Source source = new DOMSource(document);
            Result result = new StreamResult(new OutputStreamWriter(
                    new FileOutputStream(getOption("outFile"))));
            transformer.transform(source, result);
        } catch (Exception e) {
            // oops we cannot throw checked exceptions
            throw new RuntimeException(e);
        }
    }

    private String getOption(String name) {
        // there is a bug in the 1.5 apt implementation:
        // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6258929
        // this is a hack-around
        if (environment.getOptions().containsKey(name))
            return environment.getOptions().get(name);

        for (Map.Entry<String, String> entry : environment.getOptions()
                .entrySet()) {
            String key = entry.getKey();
            String[] splitted = key.split("=");
            if (splitted[0].equals("-A" + name))
                return splitted[1];
        }
        return null;
    }

    private void createElement(Document doc, Element tagLibElement, Tag tag) {
        Element tagElement = doc.createElement("tag");
        tagLibElement.appendChild(tagElement);
        appendTextNode(doc, tagElement, "name", tag.getName(), false);
        appendTextNode(doc, tagElement, "tag-class", tag.getTldTagClass(),
                false);
        appendTextNode(doc, tagElement, "body-content",
                tag.getTldBodyContent(), false);
        appendTextNode(doc, tagElement, "description", tag.getDescription(),
                true);

        // save attributes
        for (TagAttribute attribute : tag.getAttributes()) {
            createElement(doc, tagElement, attribute);
        }

        appendTextNode(doc, tagElement, "dynamic-attributes", String.valueOf(tag.isAllowDynamicAttributes()), false);
    }

    private void createElement(Document doc, Element tagElement,
            TagAttribute attribute) {
        Element attributeElement = doc.createElement("attribute");
        tagElement.appendChild(attributeElement);
        appendTextNode(doc, attributeElement, "name", attribute.getName(),
                false);
        appendTextNode(doc, attributeElement, "required", String
                .valueOf(attribute.isRequired()), false);
        appendTextNode(doc, attributeElement, "rtexprvalue", String
                .valueOf(attribute.isRtexprvalue()), false);
        appendTextNode(doc, attributeElement, "description", attribute
                .getDescription(), true);
    }

    private void appendTextNode(Document doc, Element element, String name,
            String text, boolean cdata) {
        Text textNode = cdata ? doc.createCDATASection(text) : doc
                .createTextNode(text);
        Element newElement = doc.createElement(name);
        newElement.appendChild(textNode);
        element.appendChild(newElement);
    }

    /**
     * Get values of annotation
     *
     * @param declaration The annotation declaration
     * @param type
     *            The type of the annotation
     * @return name->value map of annotation values
     */
    private Map<String, Object> getValues(Declaration declaration,
            AnnotationTypeDeclaration type) {
        Map<String, Object> values = new TreeMap<String, Object>();
        Collection<AnnotationMirror> annotations = declaration
                .getAnnotationMirrors();
        // iterate over the mirrors.

        for (AnnotationMirror mirror : annotations) {
            // if the mirror in this iteration is for our note declaration...
            if (mirror.getAnnotationType().getDeclaration().equals(type)) {
                for (AnnotationTypeElementDeclaration annotationType : mirror
                        .getElementValues().keySet()) {
                    Object value = mirror.getElementValues()
                            .get(annotationType).getValue();
                    Object defaultValue = annotationType.getDefaultValue();
                    values.put(annotationType.getSimpleName(),
                            value != null ? value : defaultValue);
                }
            }
        }

        // find default values...painful
        for (AnnotationTypeElementDeclaration annotationType : type
                .getMethods()) {
            AnnotationValue value = annotationType.getDefaultValue();
            if (value != null) {
                String name = annotationType.getSimpleName();
                if (!values.containsKey(name))
                    values.put(name, value.getValue());
            }
        }

        return values;
    }

    /**
     * Get values of annotation
     *
     * @param annotation The annotation
     * @return name->value map of annotation values
     * @throws IntrospectionException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     */
    private  Map<String, Object> getValues(Annotation annotation) throws IntrospectionException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        Map<String, Object> values = new TreeMap<String, Object>();
        //if the tag classes were on this project we could just cast to the right type
        //but they are needed on core
        Class annotationType = annotation.annotationType();

        Method[] methods = annotationType.getMethods();
        //iterate over class fields
        for(int i = 0; i < methods.length; ++i) {
            Method method = methods[i];
            if(method != null && method.getParameterTypes().length == 0) {
                Object value = method.invoke(annotation, new Object[0]);
                values.put(method.getName(), value);
            }
        }

        return values;
    }
}
