/*
 * 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 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 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 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 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 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.
     *
     * @param isMetadataComplete
     */
    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;
    }

}
