/*
 * $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, "description",
                    getOption("description"), true);
            appendTextNode(document, tagLib, "display-name",
                    getOption("displayName"), false);
            appendTextNode(document, tagLib, "tlib-version",
                    getOption("tlibVersion"), false);
            appendTextNode(document, tagLib, "short-name",
                    getOption("shortName"), false);
            appendTextNode(document, tagLib, "uri", getOption("uri"), false);

            // 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");

            //create output directory if it does not exists
            File outputFile = new File(getOption("outFile"));
            File parentDir = outputFile.getParentFile();
            if (!parentDir.exists())
                parentDir.mkdirs();

            Source source = new DOMSource(document);
            Result result = new StreamResult(new OutputStreamWriter(
                    new FileOutputStream(outputFile)));
            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, "description", tag.getDescription(),
                true);
        appendTextNode(doc, tagElement, "name", tag.getName(), false);
        appendTextNode(doc, tagElement, "tag-class", tag.getTldTagClass(),
                false);
        appendTextNode(doc, tagElement, "body-content",
                tag.getTldBodyContent(), false);

        // 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, "description", attribute
                .getDescription(), true);
        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);
    }

    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;
    }
}
