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

package org.glassfish.jaxb.runtime.v2.runtime.reflect;

import com.sun.istack.Nullable;
import org.glassfish.jaxb.runtime.api.AccessorException;
import org.glassfish.jaxb.runtime.api.JAXBRIContext;
import org.glassfish.jaxb.core.v2.model.core.Adapter;
import org.glassfish.jaxb.runtime.v2.model.impl.RuntimeModelBuilder;
import org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl;
import org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.Loader;
import org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.Receiver;
import org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallingContext;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import org.xml.sax.SAXException;

import java.lang.reflect.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Accesses a particular property of a bean.
 * <p>
 * <p>
 * This interface encapsulates the access to the actual data store.
 * The intention is to generate implementations for a particular bean
 * and a property to improve the performance.
 * <p>
 * <p>
 * Accessor can be used as a receiver. Upon receiving an object
 * it sets that to the field.
 *
 * @author Kohsuke Kawaguchi (kk@kohsuke.org)
 * @see Accessor.FieldReflection
 * @see TransducedAccessor
 */
public abstract class Accessor<BeanT, ValueT> implements Receiver {

    public final Class<ValueT> valueType;

    public Class<ValueT> getValueType() {
        return valueType;
    }

    protected Accessor(Class<ValueT> valueType) {
        this.valueType = valueType;
    }

    /**
     * Returns the optimized version of the same accessor.
     *
     * @param context The {@link JAXBContextImpl} that owns the whole thing.
     *                (See {@link RuntimeModelBuilder#context}.)
     * @return At least the implementation can return {@code this}.
     */
    public Accessor<BeanT, ValueT> optimize(@Nullable JAXBContextImpl context) {
        return this;
    }


    /**
     * Gets the value of the property of the given bean object.
     *
     * @param bean must not be null.
     * @throws AccessorException if failed to set a value. For example, the getter method
     *                           may throw an exception.
     * @since 2.0 EA1
     */
    public abstract ValueT get(BeanT bean) throws AccessorException;

    /**
     * Sets the value of the property of the given bean object.
     *
     * @param bean  must not be null.
     * @param value the value to be set. Setting value to null means resetting
     *              to the VM default value (even for primitive properties.)
     * @throws AccessorException if failed to set a value. For example, the setter method
     *                           may throw an exception.
     * @since 2.0 EA1
     */
    public abstract void set(BeanT bean, ValueT value) throws AccessorException;


    /**
     * Sets the value without adapting the value.
     * <p>
     * This ugly entry point is only used by JAX-WS.
     * See {@link JAXBRIContext#getElementPropertyAccessor}
     */
    public Object getUnadapted(BeanT bean) throws AccessorException {
        return get(bean);
    }

    /**
     * Returns true if this accessor wraps an adapter.
     * <p>
     * This method needs to be used with care, but it helps some optimization.
     */
    public boolean isAdapted() {
        return false;
    }

    /**
     * Sets the value without adapting the value.
     * <p>
     * This ugly entry point is only used by JAX-WS.
     * See {@link JAXBRIContext#getElementPropertyAccessor}
     */
    public void setUnadapted(BeanT bean, Object value) throws AccessorException {
        set(bean, (ValueT) value);
    }

    public void receive(UnmarshallingContext.State state, Object o) throws SAXException {
        try {
            set((BeanT) state.getTarget(), (ValueT) o);
        } catch (AccessorException e) {
            Loader.handleGenericException(e, true);
        } catch (IllegalAccessError iae) {
            // throw UnmarshalException instead IllegalAccesssError | Issue 475
            Loader.handleGenericError(iae);
        }
    }

    private static List<Class> nonAbstractableClasses = Arrays.asList(new Class[]{
            Object.class,
            java.util.Calendar.class,
            javax.xml.datatype.Duration.class,
            javax.xml.datatype.XMLGregorianCalendar.class,
            java.awt.Image.class,
            jakarta.activation.DataHandler.class,
            javax.xml.transform.Source.class,
            java.util.Date.class,
            java.io.File.class,
            java.net.URI.class,
            java.net.URL.class,
            Class.class,
            String.class,
            javax.xml.transform.Source.class}
    );

    public boolean isValueTypeAbstractable() {
        return !nonAbstractableClasses.contains(getValueType());
    }

    /**
     * Checks if it is not builtin jaxb class
     * @param clazz to be checked
     * @return true if it is NOT builtin class
     */
    public boolean isAbstractable(Class clazz) {
        return !nonAbstractableClasses.contains(clazz);
    }

    /**
     * Wraps this  {@link Accessor} into another {@link Accessor}
     * and performs the type adaption as necessary.
     */
    public final <T> Accessor<BeanT, T> adapt(Class<T> targetType, final Class<? extends XmlAdapter<T, ValueT>> adapter) {
        return new AdaptedAccessor<BeanT, ValueT, T>(targetType, this, adapter);
    }

    public final <T> Accessor<BeanT, T> adapt(Adapter<Type, Class> adapter) {
        return new AdaptedAccessor<BeanT, ValueT, T>(
                (Class<T>) Utils.REFLECTION_NAVIGATOR.erasure(adapter.defaultType),
                this,
                adapter.adapterType);
    }

    /**
     * Flag that will be set to true after issueing a warning
     * about the lack of permission to access non-public fields.
     */
    private static boolean accessWarned = false;


    /**
     * {@link Accessor} that uses Java reflection to access a field.
     */
    public static class FieldReflection<BeanT, ValueT> extends Accessor<BeanT, ValueT> {
        public final Field f;

        private static final Logger logger = org.glassfish.jaxb.core.Utils.getClassLogger();

        public FieldReflection(Field f) {
            this(f, false);
        }

        public FieldReflection(Field f, boolean supressAccessorWarnings) {
            super((Class<ValueT>) f.getType());
            this.f = f;

            int mod = f.getModifiers();
            if (!Modifier.isPublic(mod) || Modifier.isFinal(mod) || !Modifier.isPublic(f.getDeclaringClass().getModifiers())) {
                try {
                    // attempt to make it accessible, but do so in the security context of the calling application.
                    // don't do this in the doPrivilege block
                    f.setAccessible(true);
                } catch (SecurityException e) {
                    if ((!accessWarned) && (!supressAccessorWarnings)) {
                        // this happens when we don't have enough permission.
                        logger.log(Level.WARNING, Messages.UNABLE_TO_ACCESS_NON_PUBLIC_FIELD.format(
                                f.getDeclaringClass().getName(),
                                f.getName()),
                                e);
                    }
                    accessWarned = true;
                }
            }
        }

        public ValueT get(BeanT bean) {
            try {
                return (ValueT) f.get(bean);
            } catch (IllegalAccessException e) {
                throw new IllegalAccessError(e.getMessage());
            }
        }

        public void set(BeanT bean, ValueT value) {
            try {
                if (value == null)
                    value = (ValueT) uninitializedValues.get(valueType);
                f.set(bean, value);
            } catch (IllegalAccessException e) {
                throw new IllegalAccessError(e.getMessage());
            }
        }

        @Override
        public Accessor<BeanT, ValueT> optimize(JAXBContextImpl context) {
            return this;
        }
    }

    /**
     * Read-only access to {@link Field}. Used to handle a static field.
     */
    public static final class ReadOnlyFieldReflection<BeanT, ValueT> extends FieldReflection<BeanT, ValueT> {
        public ReadOnlyFieldReflection(Field f, boolean supressAccessorWarnings) {
            super(f, supressAccessorWarnings);
        }
        public ReadOnlyFieldReflection(Field f) {
            super(f);
        }

        @Override
        public void set(BeanT bean, ValueT value) {
            // noop
        }

        @Override
        public Accessor<BeanT, ValueT> optimize(JAXBContextImpl context) {
            return this;
        }
    }


    /**
     * {@link Accessor} that uses Java reflection to access a getter and a setter.
     */
    public static class GetterSetterReflection<BeanT, ValueT> extends Accessor<BeanT, ValueT> {
        public final Method getter;
        public final Method setter;

        private static final Logger logger = org.glassfish.jaxb.core.Utils.getClassLogger();

        public GetterSetterReflection(Method getter, Method setter) {
            super(
                    (Class<ValueT>) (getter != null ?
                            getter.getReturnType() :
                            setter.getParameterTypes()[0]));
            this.getter = getter;
            this.setter = setter;

            if (getter != null)
                makeAccessible(getter);
            if (setter != null)
                makeAccessible(setter);
        }

        private void makeAccessible(Method m) {
            if (!Modifier.isPublic(m.getModifiers()) || !Modifier.isPublic(m.getDeclaringClass().getModifiers())) {
                try {
                    m.setAccessible(true);
                } catch (SecurityException e) {
                    if (!accessWarned)
                        // this happens when we don't have enough permission.
                        logger.log(Level.WARNING, Messages.UNABLE_TO_ACCESS_NON_PUBLIC_FIELD.format(
                                m.getDeclaringClass().getName(),
                                m.getName()),
                                e);
                    accessWarned = true;
                }
            }
        }

        public ValueT get(BeanT bean) throws AccessorException {
            try {
                return (ValueT) getter.invoke(bean);
            } catch (IllegalAccessException e) {
                throw new IllegalAccessError(e.getMessage());
            } catch (InvocationTargetException e) {
                throw handleInvocationTargetException(e);
            }
        }

        public void set(BeanT bean, ValueT value) throws AccessorException {
            try {
                if (value == null)
                    value = (ValueT) uninitializedValues.get(valueType);
                setter.invoke(bean, value);
            } catch (IllegalAccessException e) {
                throw new IllegalAccessError(e.getMessage());
            } catch (InvocationTargetException e) {
                throw handleInvocationTargetException(e);
            }
        }

        private AccessorException handleInvocationTargetException(InvocationTargetException e) {
            // don't block a problem in the user code
            Throwable t = e.getTargetException();
            if (t instanceof RuntimeException)
                throw (RuntimeException) t;
            if (t instanceof Error)
                throw (Error) t;

            // otherwise it's a checked exception.
            // I'm not sure how to handle this.
            // we can throw a checked exception from here,
            // but because get/set would be called from so many different places,
            // the handling would be tedious.
            return new AccessorException(t);
        }

        @Override
        public Accessor<BeanT, ValueT> optimize(JAXBContextImpl context) {
            return this;
        }
    }

    /**
     * A version of {@link GetterSetterReflection} that doesn't have any setter.
     * <p>
     * <p>
     * This provides a user-friendly error message.
     */
    public static class GetterOnlyReflection<BeanT, ValueT> extends GetterSetterReflection<BeanT, ValueT> {
        public GetterOnlyReflection(Method getter) {
            super(getter, null);
        }

        @Override
        public void set(BeanT bean, ValueT value) throws AccessorException {
            throw new AccessorException(Messages.NO_SETTER.format(getter.toString()));
        }
    }

    /**
     * A version of {@link GetterSetterReflection} thaat doesn't have any getter.
     * <p>
     * <p>
     * This provides a user-friendly error message.
     */
    public static class SetterOnlyReflection<BeanT, ValueT> extends GetterSetterReflection<BeanT, ValueT> {
        public SetterOnlyReflection(Method setter) {
            super(null, setter);
        }

        @Override
        public ValueT get(BeanT bean) throws AccessorException {
            throw new AccessorException(Messages.NO_GETTER.format(setter.toString()));
        }
    }

    /**
     * Gets the special {@link Accessor} used to recover from errors.
     */
    @SuppressWarnings("unchecked")
    public static <A, B> Accessor<A, B> getErrorInstance() {
        return ERROR;
    }

    private static final Accessor ERROR = new Accessor<Object, Object>(Object.class) {
        public Object get(Object o) {
            return null;
        }

        public void set(Object o, Object o1) {
        }
    };

    /**
     * {@link Accessor} for {@link JAXBElement#getValue()}.
     */
    public static final Accessor<JAXBElement, Object> JAXB_ELEMENT_VALUE = new Accessor<JAXBElement, Object>(Object.class) {
        public Object get(JAXBElement jaxbElement) {
            return jaxbElement.getValue();
        }

        public void set(JAXBElement jaxbElement, Object o) {
            jaxbElement.setValue(o);
        }
    };

    /**
     * Uninitialized map keyed by their classes.
     */
    private static final Map<Class, Object> uninitializedValues = new HashMap<Class, Object>();

    static {
/*
    static byte default_value_byte = 0;
    static boolean default_value_boolean = false;
    static char default_value_char = 0;
    static float default_value_float = 0;
    static double default_value_double = 0;
    static int default_value_int = 0;
    static long default_value_long = 0;
    static short default_value_short = 0;
*/
        uninitializedValues.put(byte.class, Byte.valueOf((byte) 0));
        uninitializedValues.put(boolean.class, false);
        uninitializedValues.put(char.class, Character.valueOf((char) 0));
        uninitializedValues.put(float.class, Float.valueOf(0));
        uninitializedValues.put(double.class, Double.valueOf(0));
        uninitializedValues.put(int.class, Integer.valueOf(0));
        uninitializedValues.put(long.class, Long.valueOf(0));
        uninitializedValues.put(short.class, Short.valueOf((short) 0));
    }

}
