/*
 * Copyright (c) 2011, 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:
//     Rick Barkhouse - 2.1 - initial implementation
package org.eclipse.persistence.jaxb.javamodel.xjc;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.persistence.dynamic.DynamicClassLoader;
import org.eclipse.persistence.exceptions.JAXBException;
import org.eclipse.persistence.jaxb.javamodel.JavaAnnotation;
import org.eclipse.persistence.jaxb.javamodel.JavaClass;
import org.eclipse.persistence.jaxb.javamodel.JavaField;

import com.sun.codemodel.JAnnotationUse;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JClassAlreadyExistsException;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JPrimitiveType;
import com.sun.codemodel.JType;

/**
 * INTERNAL:
 * <p>
 * <b>Purpose:</b> <code>JavaField</code> implementation wrapping XJC's <code>JFieldVar</code>.  Used when
 * bootstrapping a <code>DynamicJAXBContext</code> from an XML Schema.
 * </p>
 *
 * <p>
 * <b>Responsibilities:</b>
 * </p>
 * <ul>
 *    <li>Provide <code>Field</code> information from the underlying <code>JFieldVar</code>.</li>
 * </ul>
 *
 * @since EclipseLink 2.1
 *
 * @see org.eclipse.persistence.jaxb.javamodel.JavaField
 */
public class XJCJavaFieldImpl implements JavaField {

    private JFieldVar xjcField;
    private JCodeModel jCodeModel;
    private DynamicClassLoader dynamicClassLoader;
    private JavaClass owningClass;

    /**
     * Construct a new instance of <code>XJCJavaFieldImpl</code>.
     *
     * @param javaField - the XJC <code>JFieldVar</code> to be wrapped.
     * @param codeModel - the XJC <code>JCodeModel</code> this field belongs to.
     * @param loader - the <code>ClassLoader</code> used to bootstrap the <code>DynamicJAXBContext</code>.
     * @param owner - the <code>JavaClass</code> this field belongs to.
     */
    public XJCJavaFieldImpl(JFieldVar javaField, JCodeModel codeModel, DynamicClassLoader loader, JavaClass owner) {
        this.xjcField = javaField;
        this.jCodeModel = codeModel;
        this.dynamicClassLoader = loader;
        this.owningClass = owner;
    }

    /**
     * If this <code>JavaField</code> is annotated with an <code>Annotation</code> matching <code>aClass</code>,
     * return its <code>JavaAnnotation</code> representation.
     *
     * @param aClass a <code>JavaClass</code> representing the <code>Annotation</code> to look for.
     *
     * @return the <code>JavaAnnotation</code> represented by <code>aClass</code>, if one exists, otherwise return <code>null</code>.
     */
    @Override
    @SuppressWarnings("unchecked")
    public JavaAnnotation getAnnotation(JavaClass aClass) {
        if (aClass != null) {
            Collection<JAnnotationUse> annotations = xjcField.annotations();
            for (JAnnotationUse annotationUse : annotations) {
                XJCJavaAnnotationImpl xjcAnnotation = new XJCJavaAnnotationImpl(annotationUse, dynamicClassLoader);
                if (xjcAnnotation.getJavaAnnotationClass().getCanonicalName().equals(aClass.getQualifiedName())) {
                    return xjcAnnotation;
                }
            }
            // Didn't find annotation so return null
            return null;
        }
        // aClass was null so return null
        return null;
    }

    /**
     * Return all of the <code>Annotations</code> for this <code>JavaField</code>.
     *
     * @return A <code>Collection</code> containing this <code>JavaField's</code> <code>JavaAnnotations</code>.
     */
    @Override
    @SuppressWarnings("unchecked")
    public Collection<JavaAnnotation> getAnnotations() {
        ArrayList<JavaAnnotation> annotationsList = new ArrayList<>();

        Collection<JAnnotationUse> annotations = xjcField.annotations();
        for (JAnnotationUse annotationUse : annotations) {
            XJCJavaAnnotationImpl xjcAnnotation = new XJCJavaAnnotationImpl(annotationUse, dynamicClassLoader);
            annotationsList.add(xjcAnnotation);
        }
        return annotationsList;
    }

    /**
     * Returns the Java language modifiers for this <code>JavaField</code>, encoded in an integer.
     *
     * @return the <code>int</code> representing the modifiers for this field.
     *
     * @see java.lang.reflect.Modifier
     */
    @Override
    public int getModifiers() {
        return xjcField.mods().getValue();
    }

    /**
     * Returns the name of this <code>JavaField</code>.
     *
     * @return the <code>String</code> name of this <code>JavaField</code>.
     */
    @Override
    public String getName() {
        return xjcField.name();
    }

    /**
     * Returns the <code>JavaClass</code> representing the type of this <code>JavaField</code>.
     *
     * @return the type of this <code>JavaField</code> as a <code>JavaClass</code>.
     */
    @Override
    @SuppressWarnings("unchecked")
    public JavaClass getResolvedType() {
        JType type = xjcField.type();
        JType basis = type.erasure();
        boolean isArray = false;
        boolean isPrimitive = false;

        JClass classToReturn = null;

        if (type.isPrimitive()) {
            JPrimitiveType pType = (JPrimitiveType) type;
            classToReturn = pType.boxify();
        } else if (type.getClass().getName().contains("JArrayClass")) {
            isArray = true;
            classToReturn = (JClass) type;
            try {
                JType componentType = type.elementType();
                if (componentType.isPrimitive()) {
                    isPrimitive = true;
                }
            } catch (Exception e) {
                throw JAXBException.errorCreatingDynamicJAXBContext(e);
            }
        } else {
            try {
                classToReturn = jCodeModel._class(basis != null ? basis.fullName() : type.fullName());
            } catch (JClassAlreadyExistsException ex) {
                classToReturn = jCodeModel._getClass(basis != null ? basis.fullName() : type.fullName());
            }
        }

        if (basis instanceof JClass) {
            List<JClass> args = ((JClass) type).getTypeParameters();
            for (JClass jClass : args) {
                ((JDefinedClass) classToReturn).generify("param", jClass);
            }
        }

        String className = classToReturn.fullName();
        if (isArray) {
            className += "[]";
        }

        if (((XJCJavaClassImpl) getOwningClass()).getJavaModel() != null) {
            return ((XJCJavaClassImpl) getOwningClass()).getJavaModel().getClass(className);
        }
        return new XJCJavaClassImpl((JDefinedClass) classToReturn, jCodeModel, dynamicClassLoader, isArray, isPrimitive);
    }

    /**
     * Indicates if this <code>JavaField</code> is <code>final</code>.
     *
     * @return <code>true</code> if this <code>JavaField</code> is <code>final</code>, otherwise <code>false</code>.
     */
    @Override
    public boolean isFinal() {
        return Modifier.isFinal(getModifiers());
    }

    /**
     * Indicates if this <code>JavaField</code> is <code>abstract</code>.
     *
     * @return <code>true</code> if this <code>JavaField</code> is <code>abstract</code>, otherwise <code>false</code>.
     */
    @Override
    public boolean isAbstract() {
        return Modifier.isAbstract(getModifiers());
    }

    /**
     * Indicates if this <code>JavaField</code> is <code>private</code>.
     *
     * @return <code>true</code> if this <code>JavaField</code> is <code>private</code>, otherwise <code>false</code>.
     */
    @Override
    public boolean isPrivate() {
        return Modifier.isPrivate(getModifiers());
    }

    /**
     * Indicates if this <code>JavaField</code> is <code>protected</code>.
     *
     * @return <code>true</code> if this <code>JavaField</code> is <code>protected</code>, otherwise <code>false</code>.
     */
    @Override
    public boolean isProtected() {
        return Modifier.isProtected(getModifiers());
    }

    /**
     * Indicates if this <code>JavaField</code> is <code>public</code>.
     *
     * @return <code>true</code> if this <code>JavaField</code> is <code>public</code>, otherwise <code>false</code>.
     */
    @Override
    public boolean isPublic() {
        return Modifier.isPublic(getModifiers());
    }

    /**
     * Indicates if this <code>JavaField</code> is <code>static</code>.
     *
     * @return <code>true</code> if this <code>JavaField</code> is <code>static</code>, otherwise <code>false</code>.
     */
    @Override
    public boolean isStatic() {
        return Modifier.isStatic(getModifiers());
    }

    /**
     * Not supported.
     */
    @Override
    public boolean isSynthetic() {
        throw new UnsupportedOperationException("isSynthetic");
    }

    /**
     * Indicates if this <code>JavaField</code> is an <code>enum</code> constant - i.e. its owner is an <code>enum</code>.
     *
     * @return <code>true</code> if this <code>JavaField</code> is an <code>enum</code> constant.
     */
    @Override
    public boolean isEnumConstant() {
        return getOwningClass().isEnum();
    }

    /**
     * If this <code>JavaField</code> is annotated with an <code>Annotation</code> matching <code>aClass</code>,
     * return its <code>JavaAnnotation</code> representation.
     *
     * @param aClass a <code>JavaClass</code> representing the <code>Annotation</code> to look for.
     *
     * @return the <code>JavaAnnotation</code> represented by <code>aClass</code>, if one exists, otherwise return <code>null</code>.
     */
    @Override
    public JavaAnnotation getDeclaredAnnotation(JavaClass aClass) {
        return getAnnotation(aClass);
    }

    /**
     * Return all of the <code>Annotations</code> for this <code>JavaField</code>.
     *
     * @return A <code>Collection</code> containing this <code>JavaField's</code> <code>JavaAnnotations</code>.
     */
    @Override
    public Collection<JavaAnnotation> getDeclaredAnnotations() {
        return getAnnotations();
    }

    /**
     * Set the <code>JavaClass</code> which contains this field.
     *
     * @param owningClass the <code>JavaClass</code> representing the owner of this <code>JavaField</code>.
     */
    public void setOwningClass(JavaClass owningClass) {
        this.owningClass = owningClass;
    }

    /**
     * Returns the <code>JavaClass</code> which contains this field.
     *
     * @return <code>JavaClass</code> representing the owner of this <code>JavaField</code>.
     */
    public JavaClass getOwningClass() {
        return this.owningClass;
    }
}
