/*
 * 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:
// dmccann - December 10/2009 - 2.0.1 - Initial implementation
package org.eclipse.persistence.jaxb.javamodel;

import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.persistence.internal.helper.ConversionManager;

/**
 * <p>
 * <b>Purpose:</b>The purpose of this class is to act as a dynamic proxy that
 * allows JDK Annotation method calls to be made on a non Annotation object.
 *
 * <p>
 * <b>Responsibilities:</b>
 * <ul>
 * <li>Create and return a dynamic proxy instance based on an Annotation class
 * and a <code>Map</code> of components (method name to value pairs)</li>
 * <li>Allow JDK Annotation method calls to be invoked on the proxy object</li>
 * </ul>
 * <p>
 * This class provides a means to invoke JDK Annotation method calls on a non
 * Annotation instance.
 *
 * @see java.lang.reflect.Proxy
 */
public class AnnotationProxy implements InvocationHandler {
    private Map<String, Object> components;
    private ConversionManager conversionMgr;
    private static final String ANNOTATION_TYPE_METHOD_NAME = "annotationType";

    /**
     * This constructor sets the <code>Map</code> of components (method name to
     * value pairs)and the ConversionManager to be used when converting values
     * in the <code>Map</code> based on the return type of the associated
     * <code>Method</code> Note that the preferred method of obtaining an
     * instance of this proxy class is via
     * {@code getProxy(Map, Class<A>, ClassLoader, ConversionManager)}
     *
     * @param components
     *            <code>Map</code> of method name to value pairs
     * @param conversionMgr
     *            <code>ConversionManager</code> instance for converting to the
     *            correct return type in the <code>invoke</code> method
     */
    private AnnotationProxy(Map<String, Object> components, ConversionManager conversionMgr) {
        this.components = components;
        this.conversionMgr = conversionMgr;
    }

    /**
     * This is the preferred way to obtain an instance of a dynamic proxy.
     *
     * The method takes a <code>ClassLoader</code> (which is used to load the
     * target <code>Annotation</code>), a <code>Class</code> (which indicates
     * the target <code>Annotation</code>, i.e.
     * <code>jakarta.xml.bind.annotation.XmlElement.class)</code>, and a
     * <code>Map</code> of method name to value pairs, which represent the
     * method names on the <code>Annotation</code> and the values that are to be
     * returned from each method call. For example, if this proxy is to be used
     * for an <code>@XmlElement</code>, the <code>Map</code> should contain the
     * following keys:
     *
     * <ul>
     * <li>defaultValue</li> <li>name</li> <li>namespace</li> <li>nillable</li>
     * <li>required</li> <li> type</li>
     * </ul>
     *
     * Following are example key/value pairs :
     *
     * <ul>
     * <li>"defaultValue", "##default"</li> <li>"name", "employee"</li> <li>
     * "namespace", "www.example.org"</li> <li>"nillable", false</li> <li>
     * "required", false</li> <li>"type",
     * jakarta.xml.bind.annotation.XmlElement.DEFAULT.class</li>
     * </ul>
     *
     * @param components
     *            <code>Map</code> of method name/value pairs for this proxy
     *            instance
     * @param annoClass
     *            The interface for the proxy class to implement
     * @param cl
     *            The <code>ClassLoader</code> to define the proxy class
     * @param conversionMgr
     *            <code>ConversionManager</code> instance for converting to the
     *            correct return type in the <code>invoke</code> method
     * @return A dynamic proxy instance based on a Java model JavaAnnotation
     */
    public static <A extends Annotation> A getProxy(Map<String, Object> components, Class<A> annoClass, ClassLoader cl, ConversionManager conversionMgr) {
        // add the 'annotationType' method name/value pair to the components map
        if (components == null) {
            components = new HashMap<String, Object>();
        }
        components.put(ANNOTATION_TYPE_METHOD_NAME, annoClass.getName());

        // Pass the classloader to the ConversionManager as well
        // conversionMgr.setLoader(cl);

        return (A) Proxy.newProxyInstance(cl, new Class[] { annoClass }, new AnnotationProxy(components, conversionMgr));
    }

    /**
     * Return the <code>Map</code> of method name/value pairs for this proxy
     * instance.
     *
     * @return <code>Map</code> of method name/value pairs for this proxy
     *         instance
     */
    public Map<String, Object> getComponents() {
        return this.components;
    }

    /**
     * Invoke a given <code>Method</code> on this proxy. The component
     * <code>Map</code> will be accessed using the given <code>Method</code>'s
     * name, and if an entry exists, the associated value is returned.
     *
     * @param proxy
     *            Satisfy the <code>InvocationHandler</code> interface - not
     *            used
     * @param method
     *            The <code>Method</code> instance corresponding to the
     *            interface method invoked on the proxy instance
     * @param args
     *            Satisfy the <code>InvocationHandler</code> interface - not
     *            used
     * @return The value from the method invocation on the proxy instance
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (components == null) {
            return null;
        }

        Class returnType = method.getReturnType();
        Object value = getComponents().get(method.getName());

        if (value == null && returnType == boolean.class) {
            return false;
        }
        if (value == null && returnType == Boolean.class) {
            return Boolean.FALSE;
        }

        if (returnType.isArray()) {
            return handleArrayData(returnType, value);
        }

        // use the ConversionManager to ensure that the correct type is returned
        return conversionMgr.convertObject(value, returnType);
    }

    private Object handleArrayData(Class returnType, Object value) {
        if (value == null) {
            return null;
        }

        Object[] data = (Object[]) value;
        Class componentType = returnType.getComponentType();
        Object[] convertedArray = (Object[]) Array.newInstance(componentType, data.length);

        for (int i = 0; i < data.length; i++) {
            convertedArray[i] = conversionMgr.convertObject(data[i], componentType);
        }

        return convertedArray;
    }

}
