/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.deltaspike.core.api.provider;

import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeShutdown;
import javax.enterprise.inject.spi.Extension;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.deltaspike.core.api.config.base.CoreBaseConfig;
import org.apache.deltaspike.core.util.ClassUtils;


/**
 * This class provides access to the {@link BeanManager} by registering the current {@link BeanManager} in an extension
 * and making it available via a singleton factory for the current application.
 *
 * <p>This is really handy when you need to access CDI functionality from places where no injection is available.</p>
 *
 * <p>If a simple but manual bean lookup is needed, it's easier to use the {@link BeanProvider}.</p>
 * 
 * <p>As soon as an application shuts down, the reference to the {@link BeanManager} is removed.</p>
 * 
 * <p>
 * Usage:

 * <pre>
 * BeanManager bm = BeanManagerProvider.getInstance().getBeanManager();</pre>
 * </p>
 * <p>
 * <b>Attention:</b> This approach is intended for use in user code at runtime. If BeanManagerProvider is used during
 * Container boot (in an Extension), non-portable behaviour results. During bootstrapping, an Extension shall
 * &#064;Inject BeanManager to get access to the underlying BeanManager (see e.g. {@link #cleanupFinalBeanManagers}).
 * This is the only way to guarantee that the right BeanManager is obtained in more complex Container scenarios.</p>
 */
public class BeanManagerProvider implements Extension
{
    private static final Logger  LOG = Logger.getLogger(BeanManagerProvider.class.getName());

    //for CDI 1.1+ delegation
    private static final Method CDI_CURRENT_METHOD;
    private static final Method CDI_CURRENT_BEAN_MANAGER_METHOD;

    private static BeanManagerProvider bmpSingleton;

    static
    {
        Class cdiClass = ClassUtils.tryToLoadClassForName("javax.enterprise.inject.spi.CDI");

        Method resolvedCdiCurrentMethod = null;
        Method resolvedCdiBeanManagerMethod = null;
        //only init methods if a cdi 1.1+ container is available and the delegation-mode isn't deactivated.
        //deactivation is e.g. useful if owb is used in "parallel mode" in a weld-based server.
        if (cdiClass != null && CoreBaseConfig.BeanManagerIntegration.DELEGATE_LOOKUP)
        {
            try
            {
                resolvedCdiCurrentMethod = cdiClass.getDeclaredMethod("current");
                resolvedCdiBeanManagerMethod = cdiClass.getDeclaredMethod("getBeanManager");
            }
            catch (Exception e)
            {
                LOG.log(Level.SEVERE, "Couldn't get method from " + cdiClass.getName(), e);
            }
        }

        //null if no init happened e.g. due to CDI 1.0 or deactivated delegation-mode
        CDI_CURRENT_METHOD = resolvedCdiCurrentMethod;
        CDI_CURRENT_BEAN_MANAGER_METHOD = resolvedCdiBeanManagerMethod;
    }

    /**
     * This data container is used for storing the BeanManager for each web application. This is needed in EAR or other
     * multi-webapp scenarios when the DeltaSpike classes (jars) are provided in a shared ClassLoader.
     */
    private static class BeanManagerInfo
    {
        /**
         * The BeanManager picked up via Extension loading.
         */
        private BeanManager loadTimeBm;

        /**
         * The final BeanManager. After the container did finally boot, we first try to resolve them from JNDI, and only
         * if we don't find any BM there we take the ones picked up at startup.
         */
        private BeanManager finalBm;

        /**
         * Whether the CDI Application has finally booted. Please note that this is only a nearby value as there is no
         * reliable event for this status in EE6.
         */
        private boolean booted;
    }

    /**
     * The BeanManagerInfo for the current ClassLoader.
     * 
     * <p><b>Attention:</b> This instance must only be used through the {@link #bmpSingleton} singleton!</p>
     */
    private volatile Map<ClassLoader, BeanManagerInfo> bmInfos = new ConcurrentHashMap<ClassLoader, BeanManagerInfo>();

    /**
     * Indicates whether the {@link BeanManagerProvider} has been initialized. Usually it's not necessary to call this
     * method in application code. It's useful e.g. for other frameworks to check if DeltaSpike and the CDI container in
     * general have been started.
     *
     * @return true if the BeanManagerProvider is ready to be used
     */
    public static boolean isActive()
    {
        // CDI#current delegation enabled, skip everything
        if (CDI_CURRENT_METHOD != null && CDI_CURRENT_BEAN_MANAGER_METHOD != null)
        {
            return bmpSingleton != null;
        }

        return bmpSingleton != null && bmpSingleton.bmInfos.containsKey(ClassUtils.getClassLoader(null));
    }

    /**
     * Returns the current provider instance which provides access to the current {@link BeanManager}.
     *
     * @throws IllegalStateException if the {@link BeanManagerProvider} isn't ready to be used. That's the case if the
     *                               environment isn't configured properly and therefore the {@link AfterBeanDiscovery}
     *                               hasn't been called before this method gets called.
     * @return the singleton BeanManagerProvider
     */
    public static BeanManagerProvider getInstance()
    {
        /*X TODO Java-EE5 support needs to be discussed
        if (bmpSingleton == null)
        {
            // workaround for some Java-EE5 environments in combination with a special
            // StartupBroadcaster for bootstrapping CDI

            // CodiStartupBroadcaster.broadcastStartup();
            // here bmp might not be null (depends on the broadcasters)
        }
        */

        if (bmpSingleton == null)
        {
            throw new IllegalStateException("No " + BeanManagerProvider.class.getName() + " in place! " +
                    "Please ensure that you configured the CDI implementation of your choice properly. " +
                    "If your setup is correct, please clear all caches and compiled artifacts.");
        }
        return bmpSingleton;
    }

    /**
     * It doesn't really matter which of the system events is used to obtain the BeanManager, but
     * {@link AfterBeanDiscovery} has been chosen since it allows all events which occur after the
     * {@link AfterBeanDiscovery} to use the {@link BeanManagerProvider}.
     *
     * @param afterBeanDiscovery event which we don't actually use ;)
     * @param beanManager        the BeanManager we store and make available.
     */
    public void setBeanManager(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager)
    {
        setBeanManagerProvider(this);

        // CDI#current delegation enabled, skip everything
        if (CDI_CURRENT_METHOD != null && CDI_CURRENT_BEAN_MANAGER_METHOD != null)
        {
            return;
        }

        BeanManagerInfo bmi = getBeanManagerInfo(ClassUtils.getClassLoader(null));
        bmi.loadTimeBm = beanManager;
    }

    /**
     * The active {@link BeanManager} for the current application (current {@link ClassLoader}). This method will throw
     * an {@link IllegalStateException} if the BeanManager cannot be found.
     *
     * @return the current BeanManager, never <code>null</code>
     *
     * @throws IllegalStateException if the BeanManager cannot be found
     */
    public BeanManager getBeanManager()
    {
        // CDI#current delegation enabled, skip everything
        if (CDI_CURRENT_METHOD != null && CDI_CURRENT_BEAN_MANAGER_METHOD != null)
        {
            return resolveBeanManagerViaStaticHelper();
        }

        BeanManagerInfo bmi = getBeanManagerInfo(ClassUtils.getClassLoader(null));

        if (!bmi.booted)
        {
            // This is a workaround for some containers with messed up EAR handling.
            // Those containers might boot up with the shared ear ClassLoader
            // and later run the WARs with their own child ClassLoaders.
            if (bmi.loadTimeBm == null)
            {
                BeanManagerInfo parentBmi = getParentBeanManagerInfo(ClassUtils.getClassLoader(null));
                if (parentBmi != null)
                {
                    bmi.loadTimeBm = parentBmi.loadTimeBm;
                }
            }
        }

        BeanManager result = bmi.finalBm;

        if (result == null)
        {
            synchronized (bmi)
            {
                result = bmi.finalBm;
                if (result == null)
                {
                    // first we look for a BeanManager from JNDI
                    result = resolveBeanManagerViaJndi();

                    if (result == null)
                    {
                        // if none found, we take the one we got from the Extension loading
                        result = bmi.loadTimeBm;
                    }

                    if (result == null)
                    {
                        throw new IllegalStateException("Unable to find BeanManager. " +
                                "Please ensure that you configured the CDI implementation of your choice properly.");
                    }

                    // store the resolved BeanManager in the result cache until #cleanupFinalBeanManagers gets called
                    // -> afterwards the next call of #getBeanManager will trigger the final lookup
                    bmi.finalBm = result;
                }
            }
        }

        return result;
    }

    /**
     * By cleaning the final BeanManager map after the deployment gets validated, premature loading of information from
     * JNDI is prevented in cases where the container might not be fully setup yet.
     *
     * This might happen if the BeanManagerProvider is used in an extension during CDI bootstrap. This should be
     * generally avoided. Instead, an injected BeanManager should be used in Extensions and propagated using setters.
     *
     * In EARs with multiple webapps, each WAR might get a different Extension. This depends on the container used.
     */
    public void cleanupFinalBeanManagers(@Observes AfterDeploymentValidation adv)
    {
        // CDI#current delegation enabled, skip everything
        if (CDI_CURRENT_METHOD != null && CDI_CURRENT_BEAN_MANAGER_METHOD != null)
        {
            return;
        }

        for (BeanManagerInfo bmi : bmpSingleton.bmInfos.values())
        {
            bmi.finalBm = null;
            bmi.booted = true;

            /*possible issue with >weld< based servers:
            if #getBeanManager gets called in a custom AfterDeploymentValidation observer >after< this observer,
            the wrong bean-manager might get stored (not deterministic due to the unspecified order of observers).
            finally a bean-manager for a single bda will be stored and returned (which isn't the bm exposed via jndi).*/
        }
    }

    /**
     * Cleanup on container shutdown.
     *
     * @param beforeShutdown CDI shutdown event
     */
    public void cleanupStoredBeanManagerOnShutdown(@Observes BeforeShutdown beforeShutdown)
    {
        // CDI#current delegation enabled, skip everything
        if (CDI_CURRENT_METHOD != null && CDI_CURRENT_BEAN_MANAGER_METHOD != null)
        {
            return;
        }

        if (bmpSingleton == null)
        {
            // this happens if there has been a failure at startup
            return;
        }

        bmpSingleton.bmInfos.remove(ClassUtils.getClassLoader(null));
    }

    /**
     * Get the BeanManager from the JNDI registry.
     *
     * @return current {@link BeanManager} which is provided via JNDI
     */
    private BeanManager resolveBeanManagerViaJndi()
    {
        try
        {
            // this location is specified in JSR-299 and must be
            // supported in all certified EE environments
            return (BeanManager) new InitialContext().lookup("java:comp/BeanManager");
        }
        catch (NamingException e)
        {
            //workaround didn't work -> return null
            return null;
        }
    }

    private BeanManager resolveBeanManagerViaStaticHelper()
    {
        if (CDI_CURRENT_METHOD != null && CDI_CURRENT_BEAN_MANAGER_METHOD != null)
        {
            try
            {
                Object cdiCurrentObject = CDI_CURRENT_METHOD.invoke(null);
                return (BeanManager) CDI_CURRENT_BEAN_MANAGER_METHOD.invoke(cdiCurrentObject);
            }
            catch (Throwable t)
            {
                LOG.log(Level.FINEST, "failed to delegate bean-manager lookup -> fallback to default.", t);
            }
        }
        return null;
    }

    /**
     * Get or create the BeanManagerInfo for the given ClassLoader.
     */
    private BeanManagerInfo getBeanManagerInfo(ClassLoader cl)
    {
        BeanManagerInfo bmi = bmpSingleton.bmInfos.get(cl);

        if (bmi == null)
        {
            synchronized (this)
            {
                bmi = bmpSingleton.bmInfos.get(cl);
                if (bmi == null)
                {
                    bmi = new BeanManagerInfo();
                    bmpSingleton.bmInfos.put(cl, bmi);
                    if (cl.getParent() != null && !bmpSingleton.bmInfos.containsKey(cl.getParent()))
                    {
                        bmpSingleton.bmInfos.put(cl.getParent(), bmi);
                    }
                }
            }
        }

        return bmi;
    }

    /**
     * This function exists to prevent findbugs from complaining about setting a static member from a non-static
     * function.
     *
     * @param beanManagerProvider the bean-manager-provider which should be used if there isn't an existing provider
     *
     * @return the first BeanManagerProvider
     */
    private static BeanManagerProvider setBeanManagerProvider(BeanManagerProvider beanManagerProvider)
    {
        if (bmpSingleton == null)
        {
            bmpSingleton = beanManagerProvider;
        }

        return bmpSingleton;
    }

    /**
     * This method recurses into the parent ClassLoaders and checks whether a BeanManagerInfo for it exists.
     *
     * @return the BeanManagerInfo of the parent ClassLoader hierarchy if any exists, or <code>null</code> if there is
     *         no {@link BeanManagerInfo} for the ClassLoaders in the hierarchy.
     */
    private BeanManagerInfo getParentBeanManagerInfo(ClassLoader classLoader)
    {
        ClassLoader parentClassLoader = classLoader.getParent();
        if (parentClassLoader == null)
        {
            return null;
        }

        BeanManagerInfo bmi = getBeanManagerInfo(parentClassLoader);
        if (bmi == null)
        {
            // recursive call up to the root ClassLoader
            bmi = getParentBeanManagerInfo(parentClassLoader);
        }

        return bmi;
    }

}
