/*
 * 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:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.jaxb.javamodel.reflection;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
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.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.persistence.exceptions.JAXBException;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.jaxb.javamodel.JavaAnnotation;
import org.eclipse.persistence.jaxb.javamodel.JavaClass;
import org.eclipse.persistence.jaxb.javamodel.JavaClassInstanceOf;
import org.eclipse.persistence.jaxb.javamodel.JavaConstructor;
import org.eclipse.persistence.jaxb.javamodel.JavaField;
import org.eclipse.persistence.jaxb.javamodel.JavaMethod;
import org.eclipse.persistence.jaxb.javamodel.JavaPackage;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;

/**
 * INTERNAL:
 * <p><b>Purpose:</b>A wrapper class for a JDK Class.  This implementation
 * of the EclipseLink JAXB 2.X Java model simply makes reflective calls on the
 * underlying JDK object.
 *
 * <p><b>Responsibilities:</b>
 * <ul>
 * <li>Provide access to the underlying JDK Class' name, package,
 * method/field names and parameters, annotations, etc.</li>
 * </ul>
 *
 * @since Oracle TopLink 11.1.1.0.0
 * @see org.eclipse.persistence.jaxb.javamodel.JavaClass
 * @see java.lang.Class
 */
public class JavaClassImpl implements JavaClass {

    protected ParameterizedType jType;
    protected Class jClass;
    protected JavaModelImpl javaModelImpl;
    protected boolean isMetadataComplete;
    protected JavaClass superClassOverride;

    protected static final String XML_REGISTRY_CLASS_NAME = "jakarta.xml.bind.annotation.XmlRegistry";

    public JavaClassImpl(Class javaClass, JavaModelImpl javaModelImpl) {
        this.jClass = javaClass;
        this.javaModelImpl = javaModelImpl;
        isMetadataComplete = false;
    }

    public JavaClassImpl(ParameterizedType javaType, Class javaClass, JavaModelImpl javaModelImpl) {
        this.jType = javaType;
        this.jClass = javaClass;
        this.javaModelImpl = javaModelImpl;
        isMetadataComplete = false;
    }

    public void setJavaModelImpl(JavaModelImpl javaModel) {
        this.javaModelImpl = javaModel;
    }
    @Override
    public Collection<JavaClass> getActualTypeArguments() {
        ArrayList<JavaClass> argCollection = new ArrayList<>();
        if (jType != null) {
            Type[] params = jType.getActualTypeArguments();
            for (Type type : params) {
                if (type instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) type;
                    argCollection.add(new JavaClassImpl(pt, (Class) pt.getRawType(), javaModelImpl));
                } else if(type instanceof WildcardType){
                    Type[] upperTypes = ((WildcardType)type).getUpperBounds();
                    if(upperTypes.length >0){
                        Type upperType = upperTypes[0];
                        if(upperType instanceof Class){
                            argCollection.add(javaModelImpl.getClass((Class) upperType));
                        }
                    }
                } else if (type instanceof Class) {
                    argCollection.add(javaModelImpl.getClass((Class) type));
                } else if(type instanceof GenericArrayType) {
                    Class genericTypeClass = (Class)((GenericArrayType)type).getGenericComponentType();
                    genericTypeClass = java.lang.reflect.Array.newInstance(genericTypeClass, 0).getClass();
                    argCollection.add(javaModelImpl.getClass(genericTypeClass));
                } else if(type instanceof TypeVariable) {
                    Type[] boundTypes = ((TypeVariable) type).getBounds();
                    if(boundTypes.length > 0) {
                        Type boundType = boundTypes[0];
                        if(boundType instanceof Class) {
                            argCollection.add(javaModelImpl.getClass((Class) boundType));
                        }
                    }
                }
            }
        }
        return argCollection;
    }

    @Override
    public String toString() {
        return getName();
    }

    /**
     * Assumes JavaType is a JavaClassImpl instance
     */
    @Override
    public JavaAnnotation getAnnotation(JavaClass arg0) {
        // the only annotation we will return if isMetadataComplete == true is XmlRegistry
        if (arg0 != null && (!isMetadataComplete || arg0.getQualifiedName().equals(XML_REGISTRY_CLASS_NAME))) {
            Class annotationClass = ((JavaClassImpl) arg0).getJavaClass();
            if (javaModelImpl.getAnnotationHelper().isAnnotationPresent(getAnnotatedElement(), annotationClass)) {
                return new JavaAnnotationImpl(this.javaModelImpl.getAnnotationHelper().getAnnotation(getAnnotatedElement(), annotationClass));
            }
        }
        return null;
    }

    @Override
    public Collection<JavaAnnotation> getAnnotations() {
        List<JavaAnnotation> annotationCollection = new ArrayList<>();
        if (!isMetadataComplete) {
            Annotation[] annotations = javaModelImpl.getAnnotationHelper().getAnnotations(getAnnotatedElement());
            for (Annotation annotation : annotations) {
                annotationCollection.add(new JavaAnnotationImpl(annotation));
            }
        }
        return annotationCollection;
    }

    @Override
    public Collection<JavaClass> getDeclaredClasses() {
        List<JavaClass> classCollection = new ArrayList<>();
        Class[] classes = jClass.getDeclaredClasses();
        for (Class javaClass : classes) {
            classCollection.add(javaModelImpl.getClass(javaClass));
        }
        return classCollection;
    }

    @Override
    public JavaField getDeclaredField(String arg0) {
        try {
            return getJavaField(jClass.getDeclaredField(arg0));
        } catch (NoSuchFieldException nsfe) {
            return null;
        }
    }

    @Override
    public Collection<JavaField> getDeclaredFields() {
        List<JavaField> fieldCollection = new ArrayList<>();
        Field[] fields = PrivilegedAccessHelper.getDeclaredFields(jClass);

        for (Field field : fields) {
            if (!field.trySetAccessible()) {
                AbstractSessionLog.getLog().log(SessionLog.FINE, SessionLog.MISC, "set_accessible_in",
                        "field", field.getName(), jClass.getName());
            }
            fieldCollection.add(getJavaField(field));
        }
        return fieldCollection;
    }

    /**
     * Assumes JavaType[] contains JavaClassImpl instances
     */
    @Override
    public JavaMethod getDeclaredMethod(String arg0, JavaClass[] arg1) {
        if (arg1 == null) {
            arg1 = new JavaClass[0];
        }
        Class[] params = new Class[arg1.length];
        for (int i=0; i<arg1.length; i++) {
            JavaClass jType = arg1[i];
            if (jType != null) {
                params[i] = ((JavaClassImpl) jType).getJavaClass();
            }
        }
        try {
            return getJavaMethod(jClass.getDeclaredMethod(arg0, params));
        } catch (NoSuchMethodException nsme) {
            return null;
        }
    }

    @Override
    public Collection<JavaMethod> getDeclaredMethods() {
        ArrayList<JavaMethod> methodCollection = new ArrayList<>();
        Method[] methods = jClass.getDeclaredMethods();
        for (Method method : methods) {
            methodCollection.add(getJavaMethod(method));
        }
        return methodCollection;
    }

    @Override
    public JavaConstructor getConstructor(JavaClass[] paramTypes) {
        if (paramTypes == null) {
            paramTypes = new JavaClass[0];
        }
        Class[] params = new Class[paramTypes.length];
        for (int i=0; i<paramTypes.length; i++) {
            JavaClass jType = paramTypes[i];
            if (jType != null) {
                params[i] = ((JavaClassImpl) jType).getJavaClass();
            }
        }
        try {
            Constructor constructor = PrivilegedAccessHelper.getConstructorFor(jClass, params, true);
            return new JavaConstructorImpl(constructor, javaModelImpl);
        } catch (NoSuchMethodException nsme) {
            return null;
        }
    }

    @Override
    public JavaConstructor getDeclaredConstructor(JavaClass[] paramTypes) {
        if (paramTypes == null) {
            paramTypes = new JavaClass[0];
        }
        Class[] params = new Class[paramTypes.length];
        for (int i=0; i<paramTypes.length; i++) {
            JavaClass jType = paramTypes[i];
            if (jType != null) {
                params[i] = ((JavaClassImpl) jType).getJavaClass();
            }
        }
        try {
            return new JavaConstructorImpl(PrivilegedAccessHelper.getDeclaredConstructorFor(this.jClass, params, true), javaModelImpl);
        } catch (NoSuchMethodException nsme) {
            return null;
        }
    }

    @Override
    public Collection<JavaConstructor> getConstructors() {
        Constructor[] constructors = this.jClass.getConstructors();
        ArrayList<JavaConstructor> constructorCollection = new ArrayList(constructors.length);
        for(Constructor next:constructors) {
            constructorCollection.add(new JavaConstructorImpl(next, javaModelImpl));
        }
        return constructorCollection;
    }

    @Override
    public Collection<JavaConstructor> getDeclaredConstructors() {
        Constructor[] constructors = this.jClass.getDeclaredConstructors();
        ArrayList<JavaConstructor> constructorCollection = new ArrayList(constructors.length);
        for(Constructor next:constructors) {
            constructorCollection.add(new JavaConstructorImpl(next, javaModelImpl));
        }
        return constructorCollection;
    }

    public JavaField getField(String arg0) {
        try {
            Field field = PrivilegedAccessHelper.getField(jClass, arg0, true);
            return getJavaField(field);
        } catch (NoSuchFieldException nsfe) {
            return null;
        }
    }

    public Collection getFields() {
        ArrayList<JavaField> fieldCollection = new ArrayList<>();
        Field[] fields = PrivilegedAccessHelper.getFields(jClass);
        for (Field field : fields) {
            fieldCollection.add(getJavaField(field));
        }
        return fieldCollection;
    }

    public Class getJavaClass() {
        return jClass;
    }

    /**
     * Assumes JavaType[] contains JavaClassImpl instances
     */
    @Override
    public JavaMethod getMethod(String arg0, JavaClass[] arg1) {
        if (arg1 == null) {
            arg1 = new JavaClass[0];
        }
        Class[] params = new Class[arg1.length];
        for (int i=0; i<arg1.length; i++) {
            JavaClass jType = arg1[i];
            if (jType != null) {
                params[i] = ((JavaClassImpl) jType).getJavaClass();
            }
        }
        try {
            Method method = PrivilegedAccessHelper.getMethod(jClass, arg0, params, true);
            return getJavaMethod(method);
        } catch (NoSuchMethodException nsme) {
            return null;
        }
    }

    @Override
    public Collection<JavaMethod> getMethods() {
        ArrayList<JavaMethod> methodCollection = new ArrayList<>();
        Method[] methods = PrivilegedAccessHelper.getMethods(jClass);
        for (Method method : methods) {
            methodCollection.add(getJavaMethod(method));
        }
        return methodCollection;
    }

    @Override
    public String getName() {
        return jClass.getName();
    }

    @Override
    public JavaPackage getPackage() {
        return new JavaPackageImpl(jClass.getPackage(), javaModelImpl, isMetadataComplete);
    }

    @Override
    public String getPackageName() {
        if(jClass.getPackage() != null){
            return jClass.getPackage().getName();
        }else{
            Class nonInnerClass = jClass;
            Class enclosingClass = jClass.getEnclosingClass();
            while(enclosingClass != null){
                nonInnerClass = enclosingClass;
                enclosingClass = nonInnerClass.getEnclosingClass();
            }
            String className = nonInnerClass.getCanonicalName();
            if(className !=null){
                int index = className.lastIndexOf('.');
                if(index > -1){
                    return className.substring(0, index);
                }
            }
        }
        return null;
    }

    @Override
    public String getQualifiedName() {
        return jClass.getName();
    }

    @Override
    public String getRawName() {
        return jClass.getCanonicalName();
    }

    @Override
    public JavaClass getSuperclass() {
        if(this.superClassOverride != null) {
            return this.superClassOverride;
        }
        if(jClass.isInterface()) {
            Class[] superInterfaces = jClass.getInterfaces();
            if(superInterfaces != null) {
                if(superInterfaces.length == 1) {
                    return javaModelImpl.getClass(superInterfaces[0]);
                } else {
                    Class parent = null;
                    for(Class next:superInterfaces) {
                        if(!(next.getName().startsWith("java.")
                                || next.getName().startsWith("javax.")
                                || next.getName().startsWith("jakarta."))) {
                            if(parent == null) {
                                parent = next;
                            } else {
                                throw JAXBException.invalidInterface(jClass.getName());
                            }
                        }
                    }
                    return javaModelImpl.getClass(parent);
                }
            }
        }
        return javaModelImpl.getClass(jClass.getSuperclass());
    }

    @Override
    public Type[] getGenericInterfaces() {
        return jClass.getGenericInterfaces();
    }

    @Override
    public Type getGenericSuperclass() {
        return jClass.getGenericSuperclass();
    }

    @Override
    public boolean hasActualTypeArguments() {
        return getActualTypeArguments().size() > 0;
    }

    public JavaField getJavaField(Field field) {
        return new JavaFieldImpl(field, javaModelImpl, isMetadataComplete);
    }

    public JavaMethod getJavaMethod(Method method) {
        return new JavaMethodImpl(method, javaModelImpl, isMetadataComplete);
    }

    public JavaClass getOwningClass() {
        return javaModelImpl.getClass(jClass.getEnclosingClass());
    }

    @Override
    public boolean isAnnotation() {
        return jClass.isAnnotation();
    }

    @Override
    public boolean isArray() {
        return jClass.isArray();
    }

    public AnnotatedElement getAnnotatedElement() {
        return jClass;
    }

    @Override
    public boolean isAssignableFrom(JavaClass arg0) {
        if (!(arg0 instanceof JavaClassImpl)) {
            return false;
        }
        if(hasCustomSuperClass(arg0)) {
            return this.customIsAssignableFrom(arg0);
        }
        return jClass.isAssignableFrom(((JavaClassImpl) arg0).getJavaClass());
    }

    private boolean customIsAssignableFrom(JavaClass arg0) {
        JavaClassImpl jClass = (JavaClassImpl)arg0;
        Class cls = jClass.getJavaClass();

        if(cls == this.jClass) {
            return true;
        }
        Class[] interfaces = cls.getInterfaces();
        for(Class nextInterface:interfaces) {
            if(nextInterface == this.jClass) {
                return true;
            }
            if(customIsAssignableFrom(javaModelImpl.getClass(nextInterface))) {
                return true;
            }
        }

        if(!(jClass.isInterface())) {
            JavaClassImpl superJavaClass = (JavaClassImpl)jClass.getSuperclass();
            if(superJavaClass.getName().equals("java.lang.Object")) {
                return this.jClass == superJavaClass.getJavaClass();
            }
            return customIsAssignableFrom(superJavaClass);
        }
        return false;
    }

    private boolean hasCustomSuperClass(JavaClass arg0) {
        if(arg0 == null) {
            return false;
        }
        if(!this.javaModelImpl.hasXmlBindings()) {
            return false;
        }
        if(!(arg0.getClass() == this.getClass())) {
            return false;
        }
        if(arg0.getName().equals("java.lang.Object")) {
            return false;
        }
        JavaClassImpl jClass = (JavaClassImpl)arg0;
        return jClass.getSuperClassOverride() != null || hasCustomSuperClass(jClass.getSuperclass());
    }

    @Override
    public boolean isEnum() {
        return jClass.isEnum();
    }

    @Override
    public boolean isInterface() {
        return jClass.isInterface();
    }

    @Override
    public boolean isMemberClass() {
        return jClass.isMemberClass();
    }

    @Override
    public boolean isPrimitive() {
        return jClass.isPrimitive();
    }

    @Override
    public boolean isAbstract() {
        return Modifier.isAbstract(getModifiers());
    }

    @Override
    public boolean isPrivate() {
        return Modifier.isPrivate(getModifiers());
    }

    @Override
    public boolean isProtected() {
        return Modifier.isProtected(getModifiers());
    }

    @Override
    public boolean isPublic() {
        return Modifier.isPublic(getModifiers());
    }

    @Override
    public boolean isStatic() {
        return Modifier.isStatic(getModifiers());
    }

    @Override
    public int getModifiers() {
        return jClass.getModifiers();
    }

    @Override
    public boolean isFinal() {
        return Modifier.isFinal(getModifiers());
    }

    @Override
    public boolean isSynthetic() {
        return jClass.isSynthetic();
    }

    @Override
    public JavaClassInstanceOf instanceOf() {
        return JavaClassInstanceOf.JAVA_CLASS_IMPL;
    }

    @Override
    public JavaClass getComponentType() {
        if(!isArray()) {
            return null;
        }
        return javaModelImpl.getClass(this.jClass.getComponentType());
    }

    public JavaClass getSuperClassOverride() {
        return superClassOverride;
    }

    public void setSuperClassOverride(JavaClass superClassOverride) {
        this.superClassOverride = superClassOverride;
    }
    /**
     * Set the indicator for XML metadata complete - if true,
     * annotations will be ignored.
     *
     */
    void setIsMetadataComplete(Boolean isMetadataComplete) {
       if(isMetadataComplete != null){
            this.isMetadataComplete = isMetadataComplete;
        }
    }

    @Override
    public JavaAnnotation getDeclaredAnnotation(JavaClass arg0) {
        // the only annotation we will return if isMetadataComplete == true is XmlRegistry
        if (arg0 != null && (!isMetadataComplete || arg0.getQualifiedName().equals(XML_REGISTRY_CLASS_NAME))) {
            Class annotationClass = ((JavaClassImpl) arg0).getJavaClass();
            Annotation[] annotations = javaModelImpl.getAnnotationHelper().getDeclaredAnnotations(getAnnotatedElement());
            for (Annotation annotation : annotations) {
                if (annotation.annotationType().equals(annotationClass)) {
                    return new JavaAnnotationImpl(annotation);
                }
            }
        }
        return null;
    }

    @Override
    public Collection getDeclaredAnnotations() {
        List<JavaAnnotation> annotationCollection = new ArrayList<>();
        if (!isMetadataComplete) {
            Annotation[] annotations = javaModelImpl.getAnnotationHelper().getDeclaredAnnotations(getAnnotatedElement());
            for (Annotation annotation : annotations) {
                annotationCollection.add(new JavaAnnotationImpl(annotation));
            }
        }
        return annotationCollection;
    }

}
