/*
 * Copyright (c) 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.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.inject.weld.internal.bean;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;

import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.enterprise.inject.spi.InjectionTargetFactory;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.Path;
import javax.ws.rs.RuntimeType;

import org.glassfish.jersey.inject.weld.internal.data.BindingBeanPair;
import org.glassfish.jersey.inject.weld.internal.inject.InitializableInstanceBinding;
import org.glassfish.jersey.inject.weld.internal.inject.InitializableSupplierInstanceBinding;
import org.glassfish.jersey.inject.weld.internal.injector.CachedConstructorAnalyzer;
import org.glassfish.jersey.inject.weld.internal.injector.InjectionUtils;
import org.glassfish.jersey.inject.weld.internal.injector.JerseyConstructorInjectionPoint;
import org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget;
import org.glassfish.jersey.inject.weld.internal.injector.JerseyTwofoldInstantiator;
import org.glassfish.jersey.inject.weld.internal.injector.WrappingJerseyInjectionTarget;
import org.glassfish.jersey.internal.inject.ClassBinding;
import org.glassfish.jersey.internal.inject.InjectionResolver;
import org.glassfish.jersey.internal.inject.PerThread;
import org.glassfish.jersey.internal.inject.SupplierClassBinding;

import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedConstructor;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType;
import org.jboss.weld.annotated.enhanced.jlr.ConstructorSignatureImpl;
import org.jboss.weld.annotated.enhanced.jlr.EnhancedAnnotatedTypeImpl;
import org.jboss.weld.annotated.slim.SlimAnnotatedType;
import org.jboss.weld.bean.builtin.BeanManagerProxy;
import org.jboss.weld.injection.ConstructorInjectionPoint;
import org.jboss.weld.injection.producer.AbstractInstantiator;
import org.jboss.weld.injection.producer.BasicInjectionTarget;
import org.jboss.weld.injection.producer.BeanInjectionTarget;
import org.jboss.weld.injection.producer.InjectionTargetService;
import org.jboss.weld.injection.producer.Instantiator;
import org.jboss.weld.injection.producer.NonProducibleInjectionTarget;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.resources.ClassTransformer;

/**
 * Helper class to register a {@link Bean} into CDI {@link BeanManager}.
 */
public abstract class BeanHelper {

    /**
     * Forbids the creation of {@link BeanHelper} instance.
     */
    private BeanHelper() {
    }

    /**
     * Registers an instance as {@link JerseyBean} into {@link BeanManager}.
     *
     * @param binding   object containing {@link javax.enterprise.inject.spi.BeanAttributes} information.
     * @param abd       {@link AfterBeanDiscovery} event.
     * @param resolvers all registered injection resolvers.
     * @param <T>       type of the instance which is registered.
     */
    public static <T> void registerBean(RuntimeType runtimeType, InitializableInstanceBinding<T> binding, AfterBeanDiscovery abd,
                                        List<InjectionResolver> resolvers, BeanManager beanManager) {
        InitializableInstanceBean<T> bean = new InitializableInstanceBean<>(runtimeType, binding);
        /*
         * Wrap into custom injection target that is able to inject the additional @Inject, @Context, @*Param fields into
         * the given service.
         */
        InjectionTarget<T> injectionTarget = new WrappingJerseyInjectionTarget<>(bean, resolvers);
        bean.setInjectionTarget(injectionTarget);
        abd.addBean(bean);
    }

    /**
     * Registers a class as {@link JerseyBean} into {@link BeanManager}.
     *
     * @param binding     object containing {@link javax.enterprise.inject.spi.BeanAttributes} information.
     * @param abd         {@link AfterBeanDiscovery} event.
     * @param resolvers   all registered injection resolvers.
     * @param beanManager currently used bean manager.
     * @param <T>         type of the class which is registered.
     */
    public static <T> BindingBeanPair registerBean(RuntimeType runtimeType, ClassBinding<T> binding, AfterBeanDiscovery abd,
                                                   Collection<InjectionResolver> resolvers, BeanManager beanManager) {
        AnnotatedType<T> annotatedType = beanManager.createAnnotatedType(binding.getService());
        InjectionTargetFactory<T> injectionTargetFactory = beanManager.getInjectionTargetFactory(annotatedType);
        InjectionTarget<T> injectionTarget = injectionTargetFactory.createInjectionTarget(null);

        ClassBean<T> bean = new ClassBean<>(runtimeType, binding);
        bean.setInjectionTarget(getJerseyInjectionTarget(binding.getService(), injectionTarget, bean, resolvers));
        abd.addBean(bean);

        return new BindingBeanPair(binding, bean);
    }

    /**
     * Registers an instance supplier and its provided value as {@link JerseyBean}s into {@link BeanManager}.
     *
     * @param binding object containing {@link javax.enterprise.inject.spi.BeanAttributes} information.
     * @param abd     {@link AfterBeanDiscovery} event.
     * @param <T>     type of the instance which is registered.
     */
    public static <T> void registerSupplier(RuntimeType runtimeType, InitializableSupplierInstanceBinding<T> binding,
                                            AfterBeanDiscovery abd, BeanManager beanManager) {
        /*
         * CDI does not provide sufficient support for ThreadScoped Supplier
         */
        if (binding.getScope() == PerThread.class) {
            BeanManagerImpl manager;
            if (beanManager instanceof BeanManagerProxy) {
                manager = ((BeanManagerProxy) beanManager).unwrap();
            } else {
                manager = (BeanManagerImpl) beanManager;
            }
            abd.addBean(new InitializableSupplierThreadScopeBean(runtimeType, binding, manager));
        } else {
            abd.addBean(new InitializableSupplierInstanceBean<>(runtimeType, binding));
            abd.addBean(new InitializableSupplierInstanceBeanBridge<>(runtimeType, binding));
        }
    }

    /**
     * Registers a class supplier and its provided value as {@link JerseyBean}s into {@link BeanManager}.
     *
     * @param binding     object containing {@link javax.enterprise.inject.spi.BeanAttributes} information.
     * @param abd         {@link AfterBeanDiscovery} event.
     * @param resolvers   all registered injection resolvers.
     * @param beanManager currently used bean manager.
     * @param <T>         type of the class which is registered.
     */
    @SuppressWarnings("unchecked")
    public static <T> BindingBeanPair registerSupplier(RuntimeType runtimeType, SupplierClassBinding<T> binding,
            AfterBeanDiscovery abd, Collection<InjectionResolver> resolvers, BeanManager beanManager) {

        Class<Supplier<T>> supplierClass = (Class<Supplier<T>>) binding.getSupplierClass();
        AnnotatedType<Supplier<T>> annotatedType = beanManager.createAnnotatedType(supplierClass);
        InjectionTarget<Supplier<T>> injectionTarget = beanManager.createInjectionTarget(annotatedType);

        SupplierClassBean<T> supplierBean = new SupplierClassBean<>(runtimeType, binding);
        InjectionTarget<Supplier<T>> jit = getJerseyInjectionTarget(supplierClass, injectionTarget, supplierBean, resolvers);
        supplierBean.setInjectionTarget(jit);

        final SupplierBeanBridge supplierBeanBridge = new SupplierBeanBridge(runtimeType, binding, beanManager);

        abd.addBean(supplierBean);
        abd.addBean(supplierBeanBridge);

        return new BindingBeanPair(binding, supplierBean, supplierBeanBridge);
    }

    /**
     * Update ClassBinding Bean by {@link ConstructorInjectionPoint} for the client side beans.
     * @param binding The ClassBinding used to create a client side ConstructorInjectionPoint.
     * @param pair {@link BindingBeanPair} that contains the original server side Bean.
     * @param resolvers Resolvers handling Jersey specific injection annotations.
     * @param beanManager The {@link BeanManager}.
     */
    public static void updateBean(ClassBinding binding,
            BindingBeanPair pair, Collection<InjectionResolver> resolvers, BeanManager beanManager) {

        final JerseyBean bean = pair.getBeans().get(0);
        final ConstructorInjectionPoint cip = createConstructorInjectionPoint(binding, bean, resolvers, beanManager);

        if (ClassBean.class.isInstance(bean)
                && JerseyInjectionTarget.class.isInstance(((ClassBean) bean).getInjectionTarget())) {
            final JerseyTwofoldInstantiator instantiator =
                    ((JerseyInjectionTarget) ((ClassBean) bean).getInjectionTarget()).getTwofoldInstantiator();
            instantiator.setOptionalConstructorInjectionPoint(cip);
        }
    }

    /**
     * Update SupplierClassBinding Bean by {@link ConstructorInjectionPoint} for the client side beans.
     * @param binding The SupplierClassBinding used to create a client side ConstructorInjectionPoint.
     * @param pair {@link BindingBeanPair} that contains the original server side Bean.
     * @param resolvers Resolvers handling Jersey specific injection annotations.
     * @param beanManager The {@link BeanManager}.
     */
    public static void updateSupplierBean(SupplierClassBinding binding,
            BindingBeanPair pair, Collection<InjectionResolver> resolvers, BeanManager beanManager) {

        final JerseyBean bean = pair.getBeans().get(0);
        final ConstructorInjectionPoint cip = createConstructorInjectionPoint(binding, bean, resolvers, beanManager);

        if (SupplierClassBean.class.isInstance(bean)
                && JerseyInjectionTarget.class.isInstance(((SupplierClassBean) bean).getInjectionTarget())) {
            final JerseyTwofoldInstantiator instantiator =
                    ((JerseyInjectionTarget) ((SupplierClassBean) bean).getInjectionTarget()).getTwofoldInstantiator();
            instantiator.setOptionalConstructorInjectionPoint(cip);
        }
    }

    private static <T> ConstructorInjectionPoint<T> createConstructorInjectionPoint(
            SupplierClassBinding<T> binding, Bean<T> bean, Collection<InjectionResolver> resolvers, BeanManager beanManager) {

        final Class<Supplier<T>> bindingClass = (Class<Supplier<T>>) binding.getSupplierClass();
        final AnnotatedType<Supplier<T>> annotatedType = beanManager.createAnnotatedType(bindingClass);
        final InjectionTarget<Supplier<T>> injectionTarget = beanManager.createInjectionTarget(annotatedType);

        final CachedConstructorAnalyzer<Supplier<T>> analyzer =
                new CachedConstructorAnalyzer<>(bindingClass, InjectionUtils.getInjectAnnotations(resolvers));

        if (analyzer.hasCompatibleConstructor()) {
            EnhancedAnnotatedConstructor<T> constructor = createEnhancedAnnotatedType((BasicInjectionTarget) injectionTarget)
                    .getDeclaredEnhancedConstructor(new ConstructorSignatureImpl(analyzer.getConstructor()));

            JerseyConstructorInjectionPoint<T> constructorInjectionPoint = new JerseyConstructorInjectionPoint<T>(
                    constructor, bean, ((BasicInjectionTarget) injectionTarget).getBeanManager(), resolvers);
            return constructorInjectionPoint;
        }
        return null;
    }

    private static <T> ConstructorInjectionPoint<T> createConstructorInjectionPoint(
            ClassBinding<T> binding, Bean<T> bean, Collection<InjectionResolver> resolvers, BeanManager beanManager) {

        final Class<T> bindingClass = binding.getImplementationType();
        final AnnotatedType<T> annotatedType = beanManager.createAnnotatedType(bindingClass);
        final InjectionTarget<T> injectionTarget = beanManager.createInjectionTarget(annotatedType);

        final CachedConstructorAnalyzer<T> analyzer =
                new CachedConstructorAnalyzer<>(bindingClass, InjectionUtils.getInjectAnnotations(resolvers));

        if (analyzer.hasCompatibleConstructor()) {
            EnhancedAnnotatedConstructor<T> constructor = createEnhancedAnnotatedType((BasicInjectionTarget) injectionTarget)
                    .getDeclaredEnhancedConstructor(new ConstructorSignatureImpl(analyzer.getConstructor()));

            JerseyConstructorInjectionPoint<T> constructorInjectionPoint = new JerseyConstructorInjectionPoint<T>(
                    constructor, bean, ((BasicInjectionTarget) injectionTarget).getBeanManager(), resolvers);
            return constructorInjectionPoint;
        }
        return null;
    }

    private static <T> InjectionTarget<T> getJerseyInjectionTarget(Class<T> clazz, InjectionTarget<T> injectionTarget,
            Bean<T> bean, Collection<InjectionResolver> resolvers) {
        BasicInjectionTarget<T> it = (BasicInjectionTarget<T>) injectionTarget;

        /*
         * Looks at whether the DefaultInstantiator resolving a valid constructor does not met this case:
         * - No constructor with @Inject annotation is defined
         * - NoArgs constructor is defined
         * - Instantiator ignores JAX-RS valid constructor with multiple params
         */
        boolean noArgConstructor = isNoArgConstructorCase(it, clazz);

        JerseyInjectionTarget<T> jit;
        /*
         * CDI is able to find a constructor that means that the class contains only one constructor of this type:
         * - default constructor
         * - non-argument constructor
         * - multi-param constructor annotated by @Inject annotation and able to inject all parameters.
         */
        if (!noArgConstructor && injectionTarget instanceof BeanInjectionTarget) {
            jit = new JerseyInjectionTarget<>(it, bean, clazz, resolvers);

        /*
         * CDI failed during the looking for a proper constructor because of these reasons:
         * - multi-param constructor not annotated by @Inject annotation
         * - multiple constructors annotated by @Inject annotation
         * - is not able to satisfied single constructor annotated by @Inject annotation
         *
         * Therefore produced NonProducibleInjectionTarget cannot create and instance, we try to find the proper constructor
         * using JAX-RS rules:
         * - largest constructor with all annotated parameters
         *
         * If JAX-RS valid constructor is not find - InjectionException is thrown
         */
        } else if (noArgConstructor || injectionTarget instanceof NonProducibleInjectionTarget) {
            CachedConstructorAnalyzer<T> analyzer =
                    new CachedConstructorAnalyzer<>(clazz, InjectionUtils.getInjectAnnotations(resolvers));

            /*
             * Contains the analyzed class any constructor that can be injected by Jersey?
             */
            if (analyzer.hasCompatibleConstructor()) {
                EnhancedAnnotatedConstructor<T> constructor = createEnhancedAnnotatedType(it)
                        .getDeclaredEnhancedConstructor(new ConstructorSignatureImpl(analyzer.getConstructor()));

                JerseyConstructorInjectionPoint<T> constructorInjectionPoint =
                        new JerseyConstructorInjectionPoint<>(constructor, bean, it.getBeanManager(), resolvers);

                Instantiator<T> instantiator = new JerseyInstantiator<>(constructorInjectionPoint);
                jit = new JerseyInjectionTarget<>(createEnhancedAnnotatedType(it), it, bean, clazz, resolvers, instantiator);

            /*
             * Instance of this class cannot be created neither CDI nor Jersey therefore mark it as non-producible.
             */
            } else {
                return new WrappingJerseyInjectionTarget<>(it, bean, resolvers);
            }
        } else {
            throw new RuntimeException("Unknown InjectionTarget for the class: " + clazz.getTypeName());
        }

        InjectionTargetService injectionTargetService = it.getBeanManager().getServices().get(InjectionTargetService.class);
        injectionTargetService.addInjectionTargetToBeInitialized(jit.getEnhancedAnnotatedType(), jit);
        return jit;
    }

    public static <T> EnhancedAnnotatedType<T> createEnhancedAnnotatedType(BasicInjectionTarget<T> it) {
        return EnhancedAnnotatedTypeImpl.of(
                (SlimAnnotatedType<T>) it.getAnnotatedType(), ClassTransformer.instance(it.getBeanManager()));
    }

    /**
     * Looks at whether the DefaultInstantiator resolving a valid constructor does not met this case:
     * - No constructor with @Inject annotation is defined
     * - NoArgs constructor is defined
     * - Instantiator ignores JAX-RS valid constructor with multiple params
     *
     * @param it    injection target containing instantiator with resolved constructor.
     * @param clazz class which analyzed constructor belongs to.
     * @param <T>   type of the analyzed class.
     * @return {@code true} if no-arg constructor was selected while multi-params constructor exists.
     */
    private static <T> boolean isNoArgConstructorCase(BasicInjectionTarget<T> it, Class<T> clazz) {
        if (!(it instanceof NonProducibleInjectionTarget)) {
            Instantiator<T> instantiator = it.getInstantiator();
            Constructor<T> constructor = instantiator.getConstructor();
            return constructor.getParameterCount() == 0 && clazz.getConstructors().length > 1;
        }

        return false;
    }

    /**
     * Wrapper class to provide Jersey implementation of {@link Instantiator} interface.
     *
     * @param <T> type which is created by instantiator.
     */
    private static class JerseyInstantiator<T> extends AbstractInstantiator<T> {

        private final ConstructorInjectionPoint<T> injectionPoint;

        private JerseyInstantiator(ConstructorInjectionPoint<T> injectionPoint) {
            this.injectionPoint = injectionPoint;
        }

        @Override
        public ConstructorInjectionPoint<T> getConstructorInjectionPoint() {
            return injectionPoint;
        }

        @Override
        public Constructor<T> getConstructor() {
            return injectionPoint.getAnnotated().getJavaMember();
        }

        @Override
        public String toString() {
            return "JerseyInstantiator [constructor=" + injectionPoint.getMember() + "]";
        }

        @Override
        public boolean hasInterceptorSupport() {
            return false;
        }

        @Override
        public boolean hasDecoratorSupport() {
            return false;
        }
    }

    public static boolean isResourceClass(Class<?> clazz) {
        if (isJaxrsResource(clazz)) {
            return true;
        }

        for (Class<?> iface : clazz.getInterfaces()) {
            if (isJaxrsResource(iface)) {
                return true;
            }
        }

        return false;
    }

    private static boolean isJaxrsResource(Class<?> clazz) {
        if (clazz.isAnnotationPresent(Path.class)) {
            return true;
        }

        for (Method method : clazz.getMethods()) {
            if (method.isAnnotationPresent(Path.class)) {
                return true;
            }

            for (Annotation annotation : method.getAnnotations()) {
                if (annotation.annotationType().isAnnotationPresent(HttpMethod.class)) {
                    return true;
                }
            }
        }

        return false;
    }
}
