/**
 * 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.cxf.jaxb;

import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlSeeAlso;
import jakarta.xml.bind.annotation.XmlTransient;
import jakarta.xml.bind.annotation.XmlType;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
import javax.xml.namespace.QName;

import org.apache.cxf.common.classloader.ClassLoaderUtils;
import org.apache.cxf.common.jaxb.JAXBUtils;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.ASMHelper;
import org.apache.cxf.common.util.ASMHelper.ClassWriter;
import org.apache.cxf.common.util.ASMHelper.MethodVisitor;
import org.apache.cxf.common.util.ASMHelper.Opcodes;
import org.apache.cxf.common.util.ReflectionUtil;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.service.ServiceModelVisitor;
import org.apache.cxf.service.model.MessageInfo;
import org.apache.cxf.service.model.MessagePartInfo;
import org.apache.cxf.service.model.OperationInfo;
import org.apache.cxf.service.model.ServiceInfo;
import org.apache.cxf.service.model.UnwrappedOperationInfo;

/**
 * Walks the service model and sets up the classes for the context.
 */
class JAXBContextInitializer extends ServiceModelVisitor {
    private static final Logger LOG = LogUtils.getL7dLogger(JAXBContextInitializer.class);
    private Set<Class<?>> classes;
    private Collection<Object> typeReferences;
    private Set<Class<?>> globalAdapters = new HashSet<>();
    private Map<String, Object> unmarshallerProperties;

    JAXBContextInitializer(ServiceInfo serviceInfo,
                                  Set<Class<?>> classes,
                                  Collection<Object> typeReferences,
                                  Map<String, Object> unmarshallerProperties) {
        super(serviceInfo);
        this.classes = classes;
        this.typeReferences = typeReferences;
        this.unmarshallerProperties = unmarshallerProperties;
    }

    @Override
    public void begin(MessagePartInfo part) {
        Class<?> clazz = part.getTypeClass();
        if (clazz == null) {
            return;
        }

        if (Exception.class.isAssignableFrom(clazz)) {
            //exceptions are handled special, make sure we mark it
            part.setProperty(JAXBDataBinding.class.getName() + ".CUSTOM_EXCEPTION",
                             Boolean.TRUE);
        }
        boolean isFromWrapper = part.getMessageInfo().getOperation().isUnwrapped();
        if (isFromWrapper
            && !Boolean.TRUE.equals(part.getProperty("messagepart.isheader"))) {
            UnwrappedOperationInfo uop = (UnwrappedOperationInfo)part.getMessageInfo().getOperation();
            OperationInfo op = uop.getWrappedOperation();
            MessageInfo inf = null;
            if (uop.getInput() == part.getMessageInfo()) {
                inf = op.getInput();
            } else if (uop.getOutput() == part.getMessageInfo()) {
                inf = op.getOutput();
            }
            if (inf != null
                && inf.getFirstMessagePart().getTypeClass() != null) {
                //if the wrapper has a type class, we don't need to do anything
                //as everything would have been discovered when walking the
                //wrapper type (unless it's a header which wouldn't be in the wrapper)
                return;
            }
        }
        if (isFromWrapper
            && clazz.isArray()
            && !Byte.TYPE.equals(clazz.getComponentType())) {
            clazz = clazz.getComponentType();
        }

        Annotation[] a = (Annotation[])part.getProperty("parameter.annotations");
        checkForAdapter(clazz, a);

        Type genericType = (Type) part.getProperty("generic.type");
        if (genericType != null) {
            boolean isList = Collection.class.isAssignableFrom(clazz);
            if (isFromWrapper) {
                if (genericType instanceof Class
                    && ((Class<?>)genericType).isArray()) {
                    Class<?> cl2 = (Class<?>)genericType;
                    if (cl2.isArray()
                        && !Byte.TYPE.equals(cl2.getComponentType())) {
                        genericType = cl2.getComponentType();
                    }
                    addType(genericType);
                } else if (!isList) {
                    addType(genericType);
                }
            } else {
                addType(genericType, true);
            }

            if (isList
                && genericType instanceof ParameterizedType) {
                ParameterizedType pt = (ParameterizedType) genericType;
                if (pt.getActualTypeArguments().length > 0
                    && pt.getActualTypeArguments()[0] instanceof Class) {

                    Class<? extends Object> arrayCls =
                        Array.newInstance((Class<?>) pt.getActualTypeArguments()[0], 0).getClass();
                    clazz = arrayCls;
                    part.setTypeClass(clazz);
                    if (isFromWrapper) {
                        addType(clazz.getComponentType(), true);
                    }
                } else if (pt.getActualTypeArguments().length > 0
                    && pt.getActualTypeArguments()[0] instanceof GenericArrayType) {
                    GenericArrayType gat = (GenericArrayType)pt.getActualTypeArguments()[0];
                    gat.getGenericComponentType();
                    Class<? extends Object> arrayCls =
                        Array.newInstance((Class<?>) gat.getGenericComponentType(), 0).getClass();
                    clazz = Array.newInstance(arrayCls, 0).getClass();
                    part.setTypeClass(clazz);
                    if (isFromWrapper) {
                        addType(clazz.getComponentType(), true);
                    }
                }
            }
            if (isFromWrapper && isList) {
                clazz = null;
            }
        }
        if (clazz != null) {
            if (!isFromWrapper
                && clazz.getAnnotation(XmlRootElement.class) == null
                && clazz.getAnnotation(XmlType.class) != null
                && StringUtils.isEmpty(clazz.getAnnotation(XmlType.class).name())) {
                Object ref = createTypeReference(part.getName(), clazz);
                if (ref != null) {
                    typeReferences.add(ref);
                }
            }

            addClass(clazz);
        }
    }

    private void checkForAdapter(Class<?> clazz, Annotation[] anns) {
        if (anns != null) {
            for (Annotation a : anns) {
                if (XmlJavaTypeAdapter.class.isAssignableFrom(a.annotationType())) {
                    Type t = Utils.getTypeFromXmlAdapter((XmlJavaTypeAdapter)a);
                    if (t != null) {
                        addType(t);
                    }
                }
            }
        }
        XmlJavaTypeAdapter xjta = clazz.getAnnotation(XmlJavaTypeAdapter.class);
        if (xjta != null) {
            Type t = Utils.getTypeFromXmlAdapter(xjta);
            if (t != null) {
                addType(t);
            }
        }
        if (clazz.getPackage() != null) {
            XmlJavaTypeAdapters adapt = clazz.getPackage().getAnnotation(XmlJavaTypeAdapters.class);
            if (adapt != null) {
                for (XmlJavaTypeAdapter a : adapt.value()) {
                    globalAdapters.add(a.type());
                }
                for (XmlJavaTypeAdapter a : adapt.value()) {
                    Type t = Utils.getTypeFromXmlAdapter(a);
                    if (t != null) {
                        addType(t);
                    }
                }
            }
        }
    }

    private void addType(Type cls) {
        addType(cls, false);
    }
    private void addType(Type cls, boolean allowArray) {
        if (cls instanceof Class) {
            if (globalAdapters.contains(cls)) {
                return;
            }
            if (((Class<?>)cls).isArray() && !allowArray) {
                addClass(((Class<?>)cls).getComponentType());
            } else {
                addClass((Class<?>)cls);
            }
        } else if (cls instanceof ParameterizedType) {
            final ParameterizedType parameterizedType = (ParameterizedType)cls;
            addType(parameterizedType.getRawType());
            if (!parameterizedType.getRawType().equals(Enum.class)) {
                for (Type t2 : parameterizedType.getActualTypeArguments()) {
                    if (shouldTypeBeAdded(t2, parameterizedType)) {
                        addType(t2);
                    }
                }
            }
        } else if (cls instanceof GenericArrayType) {
            Class<?> ct;
            GenericArrayType gt = (GenericArrayType)cls;
            Type componentType = gt.getGenericComponentType();
            if (componentType instanceof Class) {
                ct = (Class<?>)componentType;
            } else if (componentType instanceof ParameterizedType) {
                final ParameterizedType parameterizedType = (ParameterizedType)componentType;
                final Type rawType = parameterizedType.getRawType();
                if (rawType instanceof Class) {
                    ct = (Class<?>)rawType;
                } else {
                    throw new IllegalArgumentException("Unable to determine type for " + rawType);
                }
                if (!parameterizedType.getRawType().equals(Enum.class)) {
                    for (Type t2 : parameterizedType.getActualTypeArguments()) {
                        if (shouldTypeBeAdded(t2, parameterizedType)) {
                            addType(t2);
                        }
                    }
                }
            } else {
                TypeVariable<?> tv = (TypeVariable<?>)componentType;
                Type[] bounds = tv.getBounds();
                if (bounds != null && bounds.length == 1) {
                    if (bounds[0] instanceof Class) {
                        ct = (Class<?>)bounds[0];
                    } else {
                        throw new IllegalArgumentException("Unable to determine type for: " + tv);
                    }
                } else {
                    throw new IllegalArgumentException("Unable to determine type for: " + tv);
                }
            }
            ct = Array.newInstance(ct, 0).getClass();

            addClass(ct);
        } else if (cls instanceof WildcardType) {
            for (Type t : ((WildcardType)cls).getUpperBounds()) {
                addType(t);
            }
            for (Type t : ((WildcardType)cls).getLowerBounds()) {
                addType(t);
            }
        } else if (cls instanceof TypeVariable) {
            for (Type t : ((TypeVariable<?>)cls).getBounds()) {
                addType(t);
            }
        }
    }

    private boolean shouldTypeBeAdded(final Type t2, final ParameterizedType parameterizedType) {
        if (!(t2 instanceof TypeVariable)) {
            return true;
        }
        TypeVariable<?> typeVariable = (TypeVariable<?>) t2;
        final Type[] bounds = typeVariable.getBounds();
        for (Type bound : bounds) {
            if (bound instanceof ParameterizedType && bound.equals(parameterizedType)) {
                return false;
            }
        }
        return true;
    }

    void addClass(Class<?> claz) {
        if (Throwable.class.isAssignableFrom(claz)) {
            if (!Throwable.class.equals(claz)
                && !Exception.class.equals(claz)) {
                walkReferences(claz);
            }
            addClass(String.class);
        } else if (claz.getName().startsWith("java.")
            || claz.getName().startsWith("javax.")
            || claz.getName().startsWith("jakarta.")) {
            return;
        } else {
            Class<?> cls = JAXBUtils.getValidClass(claz);
            if (cls == null
                && ReflectionUtil.getDeclaredConstructors(claz).length > 0
                && !Modifier.isAbstract(claz.getModifiers())) {
                if (LOG.isLoggable(Level.INFO)) {
                    LOG.info("Class " + claz.getName() + " does not have a default constructor which JAXB requires.");
                }
                //there is no init(), but other constructors
                Object factory = createFactory(claz, ReflectionUtil.getDeclaredConstructors(claz)[0]);
                unmarshallerProperties.put("com.sun.xml.bind.ObjectFactory", factory);
                cls = claz;
            }
            if (null != cls) {
                if (classes.contains(cls)) {
                    return;
                }

                if (!cls.isInterface()) {
                    classes.add(cls);
                }

                XmlSeeAlso xsa = cls.getAnnotation(XmlSeeAlso.class);
                if (xsa != null) {
                    for (Class<?> c : xsa.value()) {
                        addClass(c);
                    }
                }
                XmlJavaTypeAdapter xjta = cls.getAnnotation(XmlJavaTypeAdapter.class);
                if (xjta != null) {
                    //has an adapter.   We need to inspect the adapter and then
                    //return as the adapter will handle the superclass
                    //and interfaces and such
                    Type t = Utils.getTypeFromXmlAdapter(xjta);
                    if (t != null) {
                        addType(t);
                    }
                    return;
                }

                if (cls.getSuperclass() != null) {
                    //JAXB should do this, but it doesn't always.
                    //in particular, older versions of jaxb don't
                    addClass(cls.getSuperclass());
                }

                if (!cls.isInterface()) {
                    walkReferences(cls);
                }
            }
        }
    }

    private void walkReferences(Class<?> cls) {
        if (cls == null) {
            return;
        }
        if (cls.getName().startsWith("java.")
            || cls.getName().startsWith("javax.")
            || cls.getName().startsWith("jakarta.")) {
            return;
        }
        //walk the public fields/methods to try and find all the classes. JAXB will only load the
        //EXACT classes in the fields/methods if they are in a different package. Thus,
        //subclasses won't be found and the xsi:type stuff won't work at all.
        //We'll grab the public field/method types and then add the ObjectFactory stuff
        //as well as look for jaxb.index files in those packages.

        XmlAccessType accessType = Utils.getXmlAccessType(cls);

        if (accessType != XmlAccessType.PROPERTY) {   // only look for fields if we are instructed to
            //fields are accessible even if not public, must look at the declared fields
            //then walk to parents declared fields, etc...
            Field[] fields = ReflectionUtil.getDeclaredFields(cls);
            for (Field f : fields) {
                if (isFieldAccepted(f, accessType)) {
                    XmlJavaTypeAdapter xjta = Utils.getFieldXJTA(f);
                    if (xjta != null) {
                        Type t = Utils.getTypeFromXmlAdapter(xjta);
                        if (t != null) {
                            addType(t);
                            continue;
                        }
                    }
                    addType(f.getGenericType());
                }
            }
            walkReferences(cls.getSuperclass());
        }

        if (accessType != XmlAccessType.FIELD) {   // only look for methods if we are instructed to
            Method[] methods = ReflectionUtil.getDeclaredMethods(cls);
            for (Method m : methods) {
                if (isMethodAccepted(m, accessType)) {
                    XmlJavaTypeAdapter xjta = Utils.getMethodXJTA(m);
                    if (xjta != null) {
                        Type t = Utils.getTypeFromXmlAdapter(xjta);
                        if (t != null) {
                            addType(t);
                            continue;
                        }
                    }
                    addType(m.getGenericReturnType());
                    for (Type t : m.getGenericParameterTypes()) {
                        addType(t);
                    }
                }
            }
        }
    }

    /**
     * Checks if the field is accepted as a JAXB property.
     */
    static boolean isFieldAccepted(Field field, XmlAccessType accessType) {
        // We only accept non static fields which are not marked @XmlTransient or has transient modifier
        if (field.isAnnotationPresent(XmlTransient.class)
            || Modifier.isTransient(field.getModifiers())) {
            return false;
        }
        if (Modifier.isStatic(field.getModifiers())) {
            return field.isAnnotationPresent(XmlAttribute.class);
        }
        if (accessType == XmlAccessType.PUBLIC_MEMBER
            && !Modifier.isPublic(field.getModifiers())) {
            return false;
        }
        if (accessType == XmlAccessType.NONE
            || accessType == XmlAccessType.PROPERTY) {
            return checkJaxbAnnotation(field.getAnnotations());
        }
        return true;
    }

    /**
     * Checks if the method is accepted as a JAXB property getter.
     */
    static boolean isMethodAccepted(Method method, XmlAccessType accessType) {
        // We only accept non static property getters which are not marked @XmlTransient
        if (Modifier.isStatic(method.getModifiers())
                || method.isAnnotationPresent(XmlTransient.class)
                || !Modifier.isPublic(method.getModifiers())
                || "getClass".equals(method.getName())) {
            return false;
        }

        // must not have parameters and return type must not be void
        if (method.getReturnType() == Void.class || method.getReturnType() == Void.TYPE
            || method.getParameterTypes().length != 0
            || (method.getDeclaringClass().equals(Throwable.class)
            && !("getMessage".equals(method.getName())))
            || !(method.getName().startsWith("get")
                    || method.getName().startsWith("is"))) {
            return false;
        }
        int beginIndex = 3;
        if (method.getName().startsWith("is")) {
            beginIndex = 2;
        }

        Method setter = null;
        try {
            setter = method.getDeclaringClass()
                .getMethod("set" + method.getName().substring(beginIndex),
                           new Class[] {method.getReturnType()});
        } catch (Exception e) {
            //getter, but no setter
        }
        if (setter != null) {
            if (setter.isAnnotationPresent(XmlTransient.class)
                || !Modifier.isPublic(setter.getModifiers())) {
                return false;
            }
        } else if (!Collection.class.isAssignableFrom(method.getReturnType())
            && !Throwable.class.isAssignableFrom(method.getDeclaringClass())) {
            //no setter, it's not a collection (thus getter().add(...)), and
            //not an Exception,
            return false;
        }

        if (accessType == XmlAccessType.NONE
            || accessType == XmlAccessType.FIELD) {
            return checkJaxbAnnotation(method.getAnnotations());
        }
        return true;
    }

    /**
     * Checks if there are JAXB annotations among the annotations of the class member.
     * @param annotations the array of annotations from the class member
     * @return true if JAXB annotations are present, false otherwise
     */
    static boolean checkJaxbAnnotation(Annotation[] annotations) {
        // must check if there are any jaxb annotations
        Package jaxbAnnotationsPackage = XmlElement.class.getPackage();
        for (Annotation annotation : annotations) {
            if (annotation.annotationType().getPackage() == jaxbAnnotationsPackage) {
                return true;
            }
        }
        return false;
    }

    /**
     * The TypeReference class is a sun specific class that is found in two different
     * locations depending on environment. In IBM JDK the class is not available at all.
     * So we have to load it at runtime.
     *
     * @param n
     * @param cls
     * @return initiated TypeReference
     */
    private static Object createTypeReference(QName n, Class<?> cls) {
        Class<?> refClass = null;
        try {
            refClass = ClassLoaderUtils.loadClass("com.sun.xml.bind.api.TypeReference",
                                                  JAXBContextInitializer.class);
        } catch (Throwable ex) {
            try {
                refClass = ClassLoaderUtils.loadClass("com.sun.xml.internal.bind.api.TypeReference",
                                                      JAXBContextInitializer.class);
            } catch (Throwable ex2) {
                //ignore
            }
        }
        if (refClass != null) {
            try {
                return refClass.getConstructor(QName.class, Type.class, new Annotation[0].getClass()) //NOPMD
                    .newInstance(n, cls, new Annotation[0]);
            } catch (Throwable e) {
                //ignore
            }
        }
        return null;
    }

    @SuppressWarnings("unused")
    private Object createFactory(Class<?> cls, Constructor<?> contructor) {
        String newClassName = cls.getName() + "Factory";
        ASMHelper helper = new ASMHelper();
        ClassWriter cw = helper.createClassWriter();
        MethodVisitor mv;

        cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER,
                 ASMHelper.periodToSlashes(newClassName), null, "java/lang/Object", null);

        cw.visitSource(cls.getSimpleName() + "Factory" + ".java", null);

        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();

        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "create" + cls.getSimpleName(),
                            "()L" + ASMHelper.periodToSlashes(cls.getName()) + ";", null, null);
        mv.visitCode();
        String name = cls.getName().replace(".", "/");
        mv.visitTypeInsn(Opcodes.NEW, name);
        mv.visitInsn(Opcodes.DUP);
        StringBuilder paraString = new StringBuilder(32).append("(");

        for (Class<?> paraClass : contructor.getParameterTypes()) {
            mv.visitInsn(Opcodes.ACONST_NULL);
            paraString.append("Ljava/lang/Object;");
        }
        paraString.append(")V");

        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, name, "<init>", paraString.toString(), false);

        mv.visitInsn(Opcodes.ARETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();

        cw.visitEnd();
        Class<?> factoryClass = helper.loadClass(newClassName, cls, cw.toByteArray());
        try {
            return factoryClass.newInstance();
        } catch (Exception e) {
           //ignore
        }
        return null;
    }


}