/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Denise Smith -  January, 2010 - 2.0.1
package org.eclipse.persistence.jaxb.compiler;

import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Unmarshaller;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlList;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import org.eclipse.persistence.internal.jaxb.AccessorFactoryWrapper;
import org.eclipse.persistence.internal.jaxb.JaxbClassLoader;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.JAXBContext;
import org.eclipse.persistence.jaxb.TypeMappingInfo;
import org.eclipse.persistence.jaxb.javamodel.Helper;
import org.eclipse.persistence.jaxb.javamodel.JavaClass;
import org.eclipse.persistence.jaxb.javamodel.JavaField;
import org.eclipse.persistence.jaxb.javamodel.JavaMethod;
import org.eclipse.persistence.jaxb.javamodel.reflection.JavaClassImpl;
import org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes;

/**
 * Helper class for code that needs to be shared between AnnotationsProcessor,
 * MappingsGenerator, SchemaGenerator
 */
public class CompilerHelper {

    public static final String XML_LOCATION_ANNOTATION_NAME = "org.glassfish.jaxb.core.annotation.XmlLocation";
    public static final String OLD_XML_LOCATION_ANNOTATION_NAME = "com.sun.xml.bind.annotation.XmlLocation";
    public static final String INTERNAL_XML_LOCATION_ANNOTATION_NAME = "com.sun.xml.internal.bind.annotation.XmlLocation";

    private static final String XML_ACCESSOR_FACTORY_ANNOTATION_NAME = "org.glassfish.jaxb.runtime.XmlAccessorFactory";
    private static final String OLD_ACCESSOR_FACTORY_ANNOTATION_NAME = "com.sun.xml.bind.XmlAccessorFactory";
    private static final String INTERNAL_ACCESSOR_FACTORY_ANNOTATION_NAME = "com.sun.xml.internal.bind.XmlAccessorFactory";
    private static final String METADATA_MODEL_PACKAGE = "org.eclipse.persistence.jaxb.xmlmodel";

    public static Class ACCESSOR_FACTORY_ANNOTATION_CLASS = null;
    public static Method ACCESSOR_FACTORY_VALUE_METHOD = null;
    public static Class OLD_ACCESSOR_FACTORY_ANNOTATION_CLASS = null;
    public static Method OLD_ACCESSOR_FACTORY_VALUE_METHOD = null;
    public static Class INTERNAL_ACCESSOR_FACTORY_ANNOTATION_CLASS = null;
    public static Method INTERNAL_ACCESSOR_FACTORY_VALUE_METHOD = null;
    public static Class XML_LOCATION_ANNOTATION_CLASS = null;
    public static Class OLD_XML_LOCATION_ANNOTATION_CLASS = null;
    public static Class INTERNAL_XML_LOCATION_ANNOTATION_CLASS = null;

    private static JAXBContext xmlBindingsModelContext;

    static {
        try {
            ACCESSOR_FACTORY_ANNOTATION_CLASS = PrivilegedAccessHelper.getClassForName(XML_ACCESSOR_FACTORY_ANNOTATION_NAME, true, CompilerHelper.class.getClassLoader());
            ACCESSOR_FACTORY_VALUE_METHOD = PrivilegedAccessHelper.getDeclaredMethod(ACCESSOR_FACTORY_ANNOTATION_CLASS, "value", new Class[]{});
        } catch (Exception ex) {
        }

        try {
            XML_LOCATION_ANNOTATION_CLASS = PrivilegedAccessHelper.getClassForName(XML_LOCATION_ANNOTATION_NAME, true, CompilerHelper.class.getClassLoader());
        } catch (Exception ex) {
        }

        try {
            OLD_XML_LOCATION_ANNOTATION_CLASS = PrivilegedAccessHelper.getClassForName(OLD_XML_LOCATION_ANNOTATION_NAME, true, CompilerHelper.class.getClassLoader());
        } catch (Exception ex) {
        }

        try{
            OLD_ACCESSOR_FACTORY_ANNOTATION_CLASS = PrivilegedAccessHelper.getClassForName(OLD_ACCESSOR_FACTORY_ANNOTATION_NAME);
            OLD_ACCESSOR_FACTORY_VALUE_METHOD = PrivilegedAccessHelper.getDeclaredMethod(OLD_ACCESSOR_FACTORY_ANNOTATION_CLASS, "value", new Class[]{});
        } catch (Exception ex) {
        }

        try{
            INTERNAL_ACCESSOR_FACTORY_ANNOTATION_CLASS = PrivilegedAccessHelper.getClassForName(INTERNAL_ACCESSOR_FACTORY_ANNOTATION_NAME);
            INTERNAL_ACCESSOR_FACTORY_VALUE_METHOD = PrivilegedAccessHelper.getDeclaredMethod(INTERNAL_ACCESSOR_FACTORY_ANNOTATION_CLASS, "value", new Class[]{});
        } catch (Exception ex) {
        }

        try{
            INTERNAL_XML_LOCATION_ANNOTATION_CLASS = PrivilegedAccessHelper.getClassForName(INTERNAL_XML_LOCATION_ANNOTATION_NAME);
        }catch (Exception ex) {
        }


    }

    /**
     * If 2 TypeMappingInfo objects would generate the same generated class (and
     * therefore complex type) then return the existing class otherwise return
     * null.
     */
    static Class getExisitingGeneratedClass(TypeMappingInfo tmi, Map<TypeMappingInfo, Class> typeMappingInfoToGeneratedClasses, Map<TypeMappingInfo, Class> typeMappingInfoToAdapterClasses, ClassLoader loader) {

        Iterator<Map.Entry<TypeMappingInfo, Class>> iter = typeMappingInfoToGeneratedClasses.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry<TypeMappingInfo, Class> next = iter.next();
            TypeMappingInfo nextTMI = next.getKey();
            if (CompilerHelper.generatesSameComplexType(tmi, nextTMI, loader)) {
                return next.getValue();
            }
        }
        return null;
    }

    /**
     * Return true if the two TypeMappingInfoObjects should generate the same
     * complex type in the XSD
     */
    private static boolean generatesSameComplexType(TypeMappingInfo tmi1, TypeMappingInfo tmi2, ClassLoader loader) {

        org.eclipse.persistence.jaxb.xmlmodel.XmlElement element1 = null;
        org.eclipse.persistence.jaxb.xmlmodel.XmlElement element2 = null;

        if (tmi1.getXmlElement() != null) {
            element1 = getXmlElement(tmi1.getXmlElement(), loader);
        }

        if (tmi2.getXmlElement() != null) {
            element2 = getXmlElement(tmi2.getXmlElement(), loader);
        }

        Type actualType1 = getActualType(tmi1, element1);
        Type actualType2 = getActualType(tmi2, element2);

        if (!areTypesEqual(actualType1, actualType2)) {
            return false;
        }

        if (!hasSameClassName(tmi1,tmi2)) {
            return false;
        }

        boolean isXmlList1 = isXmlList(tmi1, element1);
        boolean isXmlList2 = isXmlList(tmi2, element2);

        if (isXmlList1) {
            if (!isXmlList2) {
                return false;
            }
        } else if (isXmlList2) {
            return false;
        }

        return true;
    }

    /**
     * Return true if tmi1 and tmi2 are instances of Class and have same class name.
     *
     * @param tmi1 instance of TypeMappingInfo
     * @param tmi2 instance of typeMappingInfo
     * @return true if TypeMappingInfos are instances of Class and have same class name
     */
    private static boolean hasSameClassName(TypeMappingInfo tmi1, TypeMappingInfo tmi2) {

        Type type1 = tmi1.getType();
        Type type2 = tmi2.getType();

        if (type1 != null && type2 == null) {
            return false;
        } else if (type1 == null && type2 != null) {
            return false;
        } else if (type1 instanceof Class && type2 instanceof Class){

            String typeName1 = ((Class)type1).getName();
            String typeName2 = ((Class)type2).getName();

            if (!typeName1.equals(typeName2)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Return if this TypeMappingInfo has an XmlList annotation or is specified
     * to be an xmlList in an XMLElement override
     */
    private static boolean isXmlList(TypeMappingInfo tmi, org.eclipse.persistence.jaxb.xmlmodel.XmlElement element) {
        if (element != null && element.isXmlList()) {
            return true;
        }

        if (tmi.getAnnotations() != null) {
            for (int i = 0; i < tmi.getAnnotations().length; i++) {
                java.lang.annotation.Annotation nextAnnotation = tmi.getAnnotations()[i];
                if (nextAnnotation != null && nextAnnotation instanceof XmlList) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Return true if the Types are equal. Accounts for Classes and
     * Parameterized types or any combintation of the two.
     */
    private static boolean areTypesEqual(java.lang.reflect.Type type, java.lang.reflect.Type type2) {
        // handle null
        if (type == null) {
            return type2 == null;
        } else if (type instanceof Class) {
            if (type2 instanceof ParameterizedType) {

                java.lang.reflect.Type rawType = ((ParameterizedType) type2).getRawType();
                if (!areTypesEqual(type, rawType)) {
                    return false;
                }

                java.lang.reflect.Type[] args = ((ParameterizedType) type2).getActualTypeArguments();
                for (int i = 0; i < args.length; i++) {
                    Type argType = getActualArgumentType(args[i]);
                    if (!areTypesEqual(Object.class, argType)) {
                        return false;
                    }
                }
                return true;
            } else if (type2 instanceof Class) {
                return type.equals(type2);
            } else {
                return false;
            }
        } else if (type instanceof ParameterizedType) {
            if (type2 instanceof Class) {

                java.lang.reflect.Type rawType = ((ParameterizedType) type).getRawType();
                if (!areTypesEqual(type2, rawType)) {
                    return false;
                }

                java.lang.reflect.Type[] args = ((ParameterizedType) type).getActualTypeArguments();
                for (int i = 0; i < args.length; i++) {
                    Type argType = getActualArgumentType(args[i]);
                    if (!areTypesEqual(Object.class, argType)) {
                        return false;
                    }
                }
                return true;
            } else if (type2 instanceof ParameterizedType) {
                // compare raw type
                if (!areTypesEqual(((ParameterizedType) type).getRawType(),
                        ((ParameterizedType) type2).getRawType())) {
                    return false;
                }

                java.lang.reflect.Type[] ta1 = ((ParameterizedType) type).getActualTypeArguments();
                java.lang.reflect.Type[] ta2 = ((ParameterizedType) type2).getActualTypeArguments();
                // check array length
                if (ta1.length != ta2.length) {
                    return false;
                }
                for (int i = 0; i < ta1.length; i++) {
                    Type componentType1 = getActualArgumentType(ta1[i]);
                    Type componentType2 = getActualArgumentType(ta2[i]);
                    if (!areTypesEqual(componentType1, componentType2)) {
                        return false;
                    }
                }
                return true;
            } else {
                return false;
            }
        }
        return false;
    }

    private static Type getActualArgumentType(Type argument){
        if(argument instanceof WildcardType){
            Type[] upperBounds = ((WildcardType)argument).getUpperBounds();
            if(upperBounds != null && upperBounds.length >0){
                return upperBounds[0];
            }else{
                return Object.class;
            }
        }else if (argument instanceof GenericArrayType){
            return ((GenericArrayType)argument).getGenericComponentType();
        }
        return argument;
    }

    /**
     * Convenience method for creating an XmlElement object based on a given
     * Element. The method will load the eclipselink metadata model and
     * unmarshal the Element. This assumes that the Element represents an
     * xml-element to be unmarshalled.
     *
     */
    static org.eclipse.persistence.jaxb.xmlmodel.XmlElement getXmlElement(org.w3c.dom.Element xmlElementNode, ClassLoader classLoader) {
        try {
            Unmarshaller unmarshaller = CompilerHelper.getXmlBindingsModelContext().createUnmarshaller();
            JAXBElement<org.eclipse.persistence.jaxb.xmlmodel.XmlElement> jelt = unmarshaller.unmarshal(xmlElementNode, org.eclipse.persistence.jaxb.xmlmodel.XmlElement.class);
            return jelt.getValue();
        } catch (jakarta.xml.bind.JAXBException jaxbEx) {
            throw org.eclipse.persistence.exceptions.JAXBException.couldNotUnmarshalMetadata(jaxbEx);
        }
    }

    /**
     * If adapter class is null return null If there is a marshal method that
     * returns something other than Object on the adapter class return the
     * return type of that method Otherwise return Object.class
     */
    static Class getTypeFromAdapterClass(Class adapterClass) {
        if (adapterClass != null) {
            Class<Object> declJavaType = Object.class;
            // look for marshal method
            Method[] tacMethods = PrivilegedAccessHelper.getMethods(adapterClass);
            for (int i = 0; i < tacMethods.length; i++) {
                Method method = tacMethods[i];
                if (method.getName().equals("marshal")) {
                    Class<Object> returnType = PrivilegedAccessHelper.getMethodReturnType(method);
                    if (!(returnType == declJavaType)) {
                        declJavaType = returnType;
                        return declJavaType;
                    }
                }
            }
            return declJavaType;
        }
        return null;

    }

    /**
     * If adapter class is null return null If there is a marshal method that
     * returns something other than Object on the adapter class return the
     * return type of that method Otherwise return Object.class
     */
    public static JavaClass getTypeFromAdapterClass(JavaClass adapterClass, Helper helper) {
        if (adapterClass != null) {
            //JavaClass declJavaType = Object.class;
            JavaClass declJavaType = helper.getJavaClass(Object.class);
            // look for marshal method
            Object[] tacMethods = adapterClass.getMethods().toArray();
            for (int i = 0; i < tacMethods.length; i++) {
                JavaMethod method = (JavaMethod)tacMethods[i];
                if (method.getName().equals("marshal")) {
                    JavaClass returnType = method.getReturnType();
                    if (!(returnType.getQualifiedName().equals(declJavaType.getQualifiedName()))) {
                        declJavaType = returnType;
                        return declJavaType;
                    }
                }
            }
            return declJavaType;
        }
        return null;

    }

    /**
     * Return true if the type is a Collection, List or Set
     */
    private static boolean isCollectionType(Type theType) {
        if (theType instanceof Class) {
            if (Collection.class.isAssignableFrom((Class) theType)
                    || List.class.isAssignableFrom((Class) theType)
                    || Set.class.isAssignableFrom((Class) theType)) {
                return true;
            }
            return false;
        } else if (theType instanceof ParameterizedType) {
            Type rawType = ((ParameterizedType) theType).getRawType();
            return isCollectionType(rawType);
        }
        return false;
    }

    /**
     * The actual type accounts for adapter classes or xmlelemnt types specified
     * in either an annotation or an XML override
     *
     */
    static Type getActualType(TypeMappingInfo tmi, org.eclipse.persistence.jaxb.xmlmodel.XmlElement element) {
        try {
            if (element == null) {
                if (tmi.getAnnotations() != null) {
                    for (int i = 0; i < tmi.getAnnotations().length; i++) {
                        java.lang.annotation.Annotation nextAnnotation = tmi.getAnnotations()[i];
                        if (nextAnnotation != null) {
                            if (nextAnnotation instanceof XmlJavaTypeAdapter) {
                                Class typeClass = ((XmlJavaTypeAdapter) nextAnnotation).type();
                                if (typeClass.getName().equals("jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter$DEFAULT")) {
                                    Class<? extends XmlAdapter> adapterClass = ((XmlJavaTypeAdapter) nextAnnotation).value();
                                    return getTypeFromAdapterClass(adapterClass);
                                }
                                return typeClass;
                            } else if (nextAnnotation instanceof XmlElement) {
                                Class typeClass = ((XmlElement) nextAnnotation).type();
                                if (!typeClass.getName().equals("jakarta.xml.bind.annotation.XmlElement.DEFAULT")) {
                                    final Type tmiType = tmi.getType();
                                    if (isCollectionType(tmiType)) {
                                        final Class itemType = typeClass;
                                        Type parameterizedType = new ParameterizedType() {
                                            Type[] typeArgs = { itemType };

                                            @Override
                                            public Type[] getActualTypeArguments() {
                                                return typeArgs;
                                            }

                                            @Override
                                            public Type getOwnerType() {
                                                return null;
                                            }

                                            @Override
                                            public Type getRawType() {
                                                return tmiType;
                                            }
                                        };
                                        return parameterizedType;
                                    } else {
                                        return typeClass;
                                    }
                                }
                            }
                        }

                    }
                }
                return tmi.getType();
            } else {

                // if it has an XMLElement specified
                // Check for an adapater, then check for XMLElement.type
                if (element.getXmlJavaTypeAdapter() != null) {
                    String actualType = element.getXmlJavaTypeAdapter().getType();
                    if (actualType != null && !actualType.equals("jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter.DEFAULT")) {
                        return PrivilegedAccessHelper.getClassForName(actualType);
                    } else {
                        String adapterClassName = element.getXmlJavaTypeAdapter().getValue();
                        Class<Object> adapterClass = PrivilegedAccessHelper.getClassForName(adapterClassName);
                        return getTypeFromAdapterClass(adapterClass);
                    }
                }

                if (!(element.getType().equals("jakarta.xml.bind.annotation.XmlElement.DEFAULT"))) {
                    String actualType = element.getType();

                    final Type tmiType = tmi.getType();
                    if (isCollectionType(tmiType)) {
                        final Class<Object> itemType = PrivilegedAccessHelper.getClassForName(actualType);
                        Type parameterizedType = new ParameterizedType() {
                            Type[] typeArgs = { itemType };

                            @Override
                            public Type[] getActualTypeArguments() {
                                return typeArgs;
                            }

                            @Override
                            public Type getOwnerType() {
                                return null;
                            }

                            @Override
                            public Type getRawType() {
                                return tmiType;
                            }
                        };
                        return parameterizedType;
                    } else {
                        return PrivilegedAccessHelper.getClassForName(actualType);
                    }
                }
                return tmi.getType();
            }
        } catch (Exception e) {
            return tmi.getType();
        }
    }

    /**
     * The method will load the eclipselink metadata model and return the
     * corresponding JAXBContext
     */
    public static JAXBContext getXmlBindingsModelContext() {
        if (xmlBindingsModelContext == null) {
            try {
                xmlBindingsModelContext = (JAXBContext) JAXBContextFactory.createContext(METADATA_MODEL_PACKAGE,CompilerHelper.class.getClassLoader());
            } catch (JAXBException e) {
                throw org.eclipse.persistence.exceptions.JAXBException.couldNotCreateContextForXmlModel(e);
            }
            if (xmlBindingsModelContext == null) {
                throw org.eclipse.persistence.exceptions.JAXBException.couldNotCreateContextForXmlModel();
            }
        }
        return xmlBindingsModelContext;
    }

    public static JavaClass getNextMappedSuperClass(JavaClass cls, Map<String, TypeInfo> typeInfo, Helper helper) {
        JavaClass superClass = cls.getSuperclass();

        if(superClass == null || helper.isBuiltInJavaType(cls) || superClass.getRawName().equals("java.lang.Object")){
            return null;
        }
        TypeInfo parentTypeInfo = typeInfo.get(superClass.getQualifiedName());
        if(parentTypeInfo == null || parentTypeInfo.isTransient()) {
            return getNextMappedSuperClass(superClass, typeInfo, helper);
        }

        return superClass;
    }

    public static void addClassToClassLoader(JavaClass cls, ClassLoader loader) {

        if(loader.getClass() == JaxbClassLoader.class && cls.getClass() == JavaClassImpl.class) {
            Class wrappedClass = ((JavaClassImpl)cls).getJavaClass();
            ((JaxbClassLoader)loader).putClass(wrappedClass.getName(), wrappedClass);
        }
    }

    static boolean hasNonAttributeJoinNodes(Property property) {
        if(property.isSetXmlJoinNodes()) {
            for(XmlJoinNodes.XmlJoinNode next: property.getXmlJoinNodes().getXmlJoinNode()) {
                if(!(next.getXmlPath().startsWith("@"))) {
                    return true;
                }
            }
        } else if(property.isSetXmlJoinNodesList()) {
            for(XmlJoinNodes nextNodes:property.getXmlJoinNodesList()) {
                for(XmlJoinNodes.XmlJoinNode next: nextNodes.getXmlJoinNode()) {
                    if(!(next.getXmlPath().startsWith("@"))) {
                        return true;
                    }
                }
            }

        }
        return false;
    }

    public static Object createAccessorFor(JavaClass jClass, Property property, Helper helper, AccessorFactoryWrapper accessorFactory) {
        if(!(jClass.getClass() == JavaClassImpl.class)) {
            return null;
        }
        Class beanClass = ((JavaClassImpl)jClass).getJavaClass();
        if(property.isMethodProperty()) {
            try {
                Method getMethod = null;
                Method setMethod = null;
                if(property.getGetMethodName() != null) {
                    getMethod = PrivilegedAccessHelper.getMethod(beanClass, property.getGetMethodName(), new Class[]{}, true);
                }
                if(property.getSetMethodName() != null) {
                    String setMethodParamTypeName = property.getType().getName();
                    JavaClassImpl paramType = (JavaClassImpl)helper.getJavaClass(setMethodParamTypeName);
                    Class[] setMethodParams = new Class[]{paramType.getJavaClass()};
                    setMethod = PrivilegedAccessHelper.getMethod(beanClass, property.getSetMethodName(), setMethodParams, true);
                }
                return accessorFactory.createPropertyAccessor(beanClass, getMethod, setMethod);
            } catch(Exception ex) {}
        }  else {
            try {
                Field field = PrivilegedAccessHelper.getField(beanClass, ((JavaField)property.getElement()).getName(), true);
                return accessorFactory.createFieldAccessor(beanClass, field, property.isReadOnly());
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
        return null;
    }

    public static boolean isSimpleType(TypeInfo info) {
        if (info.isEnumerationType()) {
            return true;
        }
        Property xmlValueProperty = info.getXmlValueProperty();

        boolean hasMappedAttributes = false;

        for (Property nextProp : info.getPropertyList()) {
            if (nextProp.isAttribute() && !nextProp.isTransient()) {
                hasMappedAttributes = true;
            }
        }
        hasMappedAttributes = hasMappedAttributes || info.hasPredicateProperties();

        return (xmlValueProperty != null && !hasMappedAttributes);
    }

}
