/*
 *  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.codehaus.groovy.transform;

import groovy.lang.GroovyRuntimeException;
import groovy.transform.AnnotationCollector;
import org.apache.groovy.ast.tools.ClassNodeUtils;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.AnnotatedNode;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.InnerClassNode;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.expr.AnnotationConstantExpression;
import org.codehaus.groovy.ast.expr.ArrayExpression;
import org.codehaus.groovy.ast.expr.ClassExpression;
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.MapExpression;
import org.codehaus.groovy.ast.stmt.ReturnStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.control.SourceUnit;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
import static org.codehaus.groovy.transform.trait.TraitComposer.COMPILESTATIC_CLASSNODE;
import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
import static org.objectweb.asm.Opcodes.ACC_ANNOTATION;
import static org.objectweb.asm.Opcodes.ACC_ENUM;
import static org.objectweb.asm.Opcodes.ACC_FINAL;
import static org.objectweb.asm.Opcodes.ACC_INTERFACE;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_STATIC;

/**
 * This class is the base for any annotation alias processor.
 *
 * @see AnnotationCollector
 * @see AnnotationCollectorTransform#visit(AnnotationNode, AnnotationNode, AnnotatedNode, SourceUnit)
 */
public class AnnotationCollectorTransform {

    private static List<AnnotationNode> getMeta(ClassNode cn) {
        List<AnnotationNode> meta = cn.getNodeMetaData(AnnotationCollector.class);
        if (meta == null) {
            if (cn.isPrimaryClassNode()) {
                meta = getTargetListFromAnnotations(cn);
            } else {
                meta = getTargetListFromClass(cn);
            }
            cn.setNodeMetaData(AnnotationCollector.class, meta);
        }
        return meta;
    }

    /**
     * Class used by {@link org.codehaus.groovy.control.CompilationUnit} to transform the alias class
     * into what is needed by the compiler. This means removing invalid
     * modifiers, interfaces and superclasses, as well as adding a static
     * value method returning our serialized version of the data for processing
     * from a pre-compiled state. By doing this the old annotations will be
     * removed as well
     */
    public static class ClassChanger {

        /**
         * Method to transform the given ClassNode, if it is annotated with
         * {@link AnnotationCollector}. See class description for what the
         * transformation includes.
         */
        public void transformClass(ClassNode cn) {
            AnnotationNode collector = null;
            for (AnnotationNode an : cn.getAnnotations()) {
                if (an.getClassNode().getName().equals(AnnotationCollector.class.getName())) {
                    collector = an;
                    break;
                }
            }
            if (collector == null) {
                return;
            }
            boolean legacySerialization = false;
            final Expression member = collector.getMember("serializeClass");
            if (member instanceof ClassExpression) {
                ClassExpression ce = (ClassExpression) member;
                legacySerialization = ce.getType().getName().equals(cn.getName());
            }
            ClassNode helper = cn;
            if (legacySerialization) {
                // force final class, remove interface, annotation, enum and abstract modifiers
                helper.setModifiers((ACC_FINAL | helper.getModifiers()) & ~(ACC_ENUM | ACC_INTERFACE | ACC_ANNOTATION | ACC_ABSTRACT));
                // force Object super class
                helper.setSuperClass(ClassHelper.OBJECT_TYPE);
                // force no interfaces implemented
                helper.setInterfaces(ClassNode.EMPTY_ARRAY);
            } else {
                helper = new InnerClassNode(cn, cn.getName() + "$CollectorHelper",
                        ACC_PUBLIC | ACC_STATIC | ACC_FINAL, ClassHelper.OBJECT_TYPE.getPlainNodeReference());
                cn.getModule().addClass(helper);
                helper.addAnnotation(new AnnotationNode(COMPILESTATIC_CLASSNODE));
                collector.setMember("serializeClass", new ClassExpression(helper.getPlainNodeReference()));
            }

            // add static value():Object[][] method
            List<AnnotationNode> meta = getMeta(cn);
            List<Expression> outer = new ArrayList<>(meta.size());
            for (AnnotationNode an : meta) {
                Expression serialized = serialize(an);
                outer.add(serialized);
            }

            ArrayExpression ae = new ArrayExpression(ClassHelper.OBJECT_TYPE.makeArray(), outer);
            Statement code = new ReturnStatement(ae);
            ClassNodeUtils.addGeneratedMethod(helper, "value", ACC_PUBLIC | ACC_STATIC,
                    ClassHelper.OBJECT_TYPE.makeArray().makeArray(),
                    Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, code);

            // remove annotations
            for (ListIterator<AnnotationNode> it = cn.getAnnotations().listIterator(); it.hasNext(); ) {
                AnnotationNode an = it.next();
                if (an == collector || "java.lang.annotation".equals(an.getClassNode().getPackageName())) {
                    continue;
                }
                it.remove();
            }
        }

        private Expression serialize(Expression e) {
            if (e instanceof AnnotationConstantExpression) {
                AnnotationConstantExpression ace = (AnnotationConstantExpression) e;
                return serialize((AnnotationNode) ace.getValue());
            }
            if (e instanceof ListExpression) {
                boolean annotationConstant = false;
                ListExpression le = (ListExpression) e;
                List<Expression> list = le.getExpressions();
                List<Expression> newList = new ArrayList<>(list.size());
                for (Expression exp: list) {
                    annotationConstant = annotationConstant || exp instanceof AnnotationConstantExpression;
                    newList.add(serialize(exp));
                }
                ClassNode type = ClassHelper.OBJECT_TYPE;
                if (annotationConstant) type = type.makeArray();
                return new ArrayExpression(type, newList);
            }
            if (e instanceof ConstantExpression) {
                Object obj = ((ConstantExpression) e).getValue();
                if (obj instanceof Enum) {
                    return propX(classX(obj.getClass()), e);
                }
            }
            return e;
        }

        private Expression serialize(AnnotationNode an) {
            ClassExpression type = new ClassExpression(an.getClassNode());
            type.setSourcePosition(an.getClassNode());

            MapExpression map = new MapExpression();
            for (Map.Entry<String, Expression> entry : an.getMembers().entrySet()) {
                Expression key = new ConstantExpression(entry.getKey());
                Expression val = serialize(entry.getValue());
                map.addMapEntryExpression(key, val);
            }

            return new ArrayExpression(ClassHelper.OBJECT_TYPE, Arrays.asList(type, map));
        }
    }

    /**
     * Adds a new syntax error to the source unit and then continues.
     *
     * @param message   the message
     * @param node      the node for the error report
     * @param source    the source unit for the error report
     */
    protected void addError(String message, ASTNode node, SourceUnit source) {
        source.getErrorCollector().addErrorAndContinue(message, node, source);
    }

    private List<AnnotationNode> getTargetListFromValue(AnnotationNode collector, AnnotationNode aliasAnnotationUsage, SourceUnit source) {
        Expression memberValue = collector.getMember("value");
        if (memberValue == null) {
            return Collections.emptyList();
        }
        if (!(memberValue instanceof ListExpression)) {
            addError("Annotation collector expected a list of classes, but got a "+memberValue.getClass(), collector, source);
            return Collections.emptyList();
        }
        ListExpression memberListExp = (ListExpression) memberValue;
        List<Expression> memberList = memberListExp.getExpressions();
        if (memberList.isEmpty()) {
            return Collections.emptyList();
        }
        List<AnnotationNode> ret = new ArrayList<>();
        for (Expression e : memberList) {
            AnnotationNode toAdd = new AnnotationNode(e.getType());
            toAdd.setSourcePosition(aliasAnnotationUsage);
            ret.add(toAdd);
        }
        return ret;
    }

    private static List<AnnotationNode> getStoredTargetList(AnnotationNode aliasAnnotationUsage, SourceUnit source) {
        ClassNode alias = aliasAnnotationUsage.getClassNode().redirect();
        List<AnnotationNode> ret = getMeta(alias);
        return copy(ret, aliasAnnotationUsage);
    }

    private static List<AnnotationNode> copy(List<AnnotationNode> orig, AnnotationNode aliasAnnotationUsage) {
        if (orig.isEmpty()) return orig;
        List<AnnotationNode> ret = new ArrayList<>(orig.size());
        for (AnnotationNode an : orig) {
            AnnotationNode newAn = new AnnotationNode(an.getClassNode());
            copyMembers(an, newAn);
            newAn.setSourcePosition(aliasAnnotationUsage);
            ret.add(newAn);
        }
        return ret;
    }

    private static List<AnnotationNode> getTargetListFromAnnotations(ClassNode alias) {
        List<AnnotationNode> annotations = alias.getAnnotations();
        if (annotations.size() < 2) {
            return Collections.emptyList();
        }
        List<AnnotationNode> ret = new ArrayList<>(annotations.size());
        for (AnnotationNode an : annotations) {
            ClassNode type = an.getClassNode();
            if (type.getName().equals(AnnotationCollector.class.getName())
                    || "java.lang.annotation".equals(type.getPackageName())
                    || "org.apache.groovy.lang.annotation.Incubating".equals(type.getName())) continue;
            AnnotationNode toAdd = new AnnotationNode(type);
            copyMembers(an, toAdd);
            ret.add(toAdd);
        }
        return ret;
    }

    private static void copyMembers(final AnnotationNode from, final AnnotationNode to) {
        Map<String, Expression> members = from.getMembers();
        copyMembers(members, to);
    }

    private static void copyMembers(final Map<String, Expression> members, final AnnotationNode to) {
        for (Map.Entry<String, Expression> entry : members.entrySet()) {
            to.addMember(entry.getKey(), entry.getValue());
        }
    }

    private static List<AnnotationNode> getTargetListFromClass(final ClassNode alias) {
        ClassNode cn = getSerializeClass(alias);
        Class<?> c = cn.getTypeClass();
        Object[][] data;
        try {
            Method m = c.getMethod("value");
            if (!Modifier.isStatic(m.getModifiers()))
                throw new NoSuchMethodException("non-static value()");

            data = (Object[][]) m.invoke(null);
            return makeListOfAnnotations(data);
        } catch (NoSuchMethodException | ClassCastException e) {
            throw new GroovyRuntimeException("Expecting static method `Object[][] value()`" +
                    " in " + cn.toString(false) + ". Was it compiled from a Java source?");
        } catch (Exception e) {
            throw new GroovyBugError(e);
        }
    }

    // 2.5.3 and above gets from annotation attribute otherwise self
    private static ClassNode getSerializeClass(final ClassNode alias) {
        List<AnnotationNode> collectors = alias.getAnnotations(ClassHelper.make(AnnotationCollector.class));
        if (!collectors.isEmpty()) {
            assert collectors.size() == 1;
            AnnotationNode collectorNode = collectors.get(0);
            Expression serializeClass = collectorNode.getMember("serializeClass");
            if (serializeClass instanceof ClassExpression) {
                ClassNode serializeClassType = serializeClass.getType();
                if (!serializeClassType.getName().equals(AnnotationCollector.class.getName())) {
                    return serializeClassType;
                }
            }
        }
        return alias;
    }

    private static List<AnnotationNode> makeListOfAnnotations(final Object[][] data) {
        if (data.length == 0) {
            return Collections.emptyList();
        }
        List<AnnotationNode> ret = new ArrayList<>(data.length);
        for (Object[] inner : data) {
            Class<?> anno = (Class<?>) inner[0];
            AnnotationNode toAdd = new AnnotationNode(ClassHelper.make(anno));
            ret.add(toAdd);

            @SuppressWarnings("unchecked")
            Map<String,Object> member = (Map<String, Object>) inner[1];
            if (member.isEmpty()) {
                continue;
            }
            Map<String, Expression> generated = new HashMap<>(member.size());
            for (Map.Entry<String, Object> entry : member.entrySet()) {
                generated.put(entry.getKey(), makeExpression(entry.getValue()));
            }
            copyMembers(generated, toAdd);
        }
        return ret;
    }

    private static Expression makeExpression(final Object o) {
        if (o instanceof Class) {
            return new ClassExpression(ClassHelper.make((Class<?>) o));
        }
        //TODO: value as Annotation here!
        if (o instanceof Object[][]) {
            List<AnnotationNode> annotations = makeListOfAnnotations((Object[][])o);
            ListExpression le = new ListExpression();
            for (AnnotationNode an : annotations) {
                le.addExpression(new AnnotationConstantExpression(an));
            }
            return le;
        } else if (o instanceof Object[]) {
            ListExpression le = new ListExpression();
            Object[] values = (Object[]) o;
            for (Object val : values) {
                le.addExpression(makeExpression(val));
            }
            return le;
        }
        return new ConstantExpression(o,true);
    }

    /**
     * Returns a list of AnnotationNodes for the value attribute of the given
     * AnnotationNode.
     *
     * @param collector     the node containing the value member with the list
     * @param source        the source unit for error reporting
     * @return              a list of string constants
     */
    protected List<AnnotationNode> getTargetAnnotationList(AnnotationNode collector, AnnotationNode aliasAnnotationUsage, SourceUnit source) {
        List<AnnotationNode> stored     = getStoredTargetList(aliasAnnotationUsage, source);
        List<AnnotationNode> targetList = getTargetListFromValue(collector, aliasAnnotationUsage, source);
        int size = targetList.size() + stored.size();
        if (size == 0) {
            return Collections.emptyList();
        }
        List<AnnotationNode> ret = new ArrayList<>(size);
        ret.addAll(stored);
        ret.addAll(targetList);
        return ret;
    }

    /**
     * Implementation method of the alias annotation processor. This method will
     * get the list of annotations we aliased from the collector and adds it to
     * aliasAnnotationUsage. The method will also map all members from
     * aliasAnnotationUsage to the aliased nodes. Should a member stay unmapped,
     * we will add an error. Further processing of those members is done by the
     * annotations.
     *
     * @param collector                 reference to the annotation with {@link AnnotationCollector}
     * @param aliasAnnotationUsage      reference to the place of usage of the alias
     * @param aliasAnnotated            reference to the node that has been annotated by the alias
     * @param source                    source unit for error reporting
     * @return list of the new AnnotationNodes
     */
    public List<AnnotationNode> visit(AnnotationNode collector, AnnotationNode aliasAnnotationUsage, AnnotatedNode aliasAnnotated, SourceUnit source) {
        List<AnnotationNode> ret =  getTargetAnnotationList(collector, aliasAnnotationUsage, source);
        Set<String> unusedNames = new HashSet<>(aliasAnnotationUsage.getMembers().keySet());

        for (AnnotationNode an: ret) {
            for (String name : aliasAnnotationUsage.getMembers().keySet()) {
                if (an.getClassNode().hasMethod(name, Parameter.EMPTY_ARRAY)) {
                    unusedNames.remove(name);
                    an.setMember(name, aliasAnnotationUsage.getMember(name));
                }
            }
        }

        if (!unusedNames.isEmpty()) {
            String message = "Annotation collector got unmapped names "+unusedNames.toString()+".";
            addError(message, aliasAnnotationUsage, source);
        }

        return ret;
    }
}
