/*
 * 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.bval.cdi;

import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;

import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
import javax.enterprise.inject.spi.Annotated;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
import javax.enterprise.inject.spi.CDI;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import javax.enterprise.inject.spi.ProcessBean;
import javax.validation.BootstrapConfiguration;
import javax.validation.Configuration;
import javax.validation.Constraint;
import javax.validation.Valid;
import javax.validation.Validation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.executable.ExecutableType;
import javax.validation.executable.ValidateOnExecution;

import org.apache.bval.jsr.ConfigurationImpl;
import org.apache.bval.jsr.util.ExecutableTypes;
import org.apache.bval.util.Lazy;
import org.apache.bval.util.Validate;

/**
 * CDI {@link Extension} for Apache BVal setup.
 */
public class BValExtension implements Extension {
    private static final Logger LOGGER = Logger.getLogger(BValExtension.class.getName());

    private static final AnnotatedTypeFilter DEFAULT_ANNOTATED_TYPE_FILTER =
        annotatedType -> !annotatedType.getJavaClass().getName().startsWith("org.apache.bval.");

    private static AnnotatedTypeFilter annotatedTypeFilter = DEFAULT_ANNOTATED_TYPE_FILTER;

    public static void setAnnotatedTypeFilter(AnnotatedTypeFilter annotatedTypeFilter) {
        BValExtension.annotatedTypeFilter = Validate.notNull(annotatedTypeFilter);
    }

    private boolean validatorFound = Boolean.getBoolean("bval.in-container");
    private boolean validatorFactoryFound = Boolean.getBoolean("bval.in-container");

    private final Configuration<?> config;
    private Lazy<ValidatorFactory> factory;

    private Set<ExecutableType> globalExecutableTypes;
    private boolean isExecutableValidationEnabled;

    private final Collection<Class<?>> potentiallyBValAnnotation = new HashSet<>();
    private final Collection<Class<?>> notBValAnnotation = new HashSet<>();

    public BValExtension() { // read the config, could be done in a quicker way but this let us get defaults without duplicating code
        config = Validation.byDefaultProvider().configure();
        try {
            final BootstrapConfiguration bootstrap = config.getBootstrapConfiguration();
            globalExecutableTypes =
                ExecutableTypes.interpret(bootstrap.getDefaultValidatedExecutableTypes());

            isExecutableValidationEnabled = bootstrap.isExecutableValidationEnabled();

        } catch (final Exception e) { // custom providers can throw an exception
            LOGGER.log(Level.SEVERE, e.getMessage(), e);

            globalExecutableTypes = Collections.emptySet();
            isExecutableValidationEnabled = false;
        }
    }

    public Set<ExecutableType> getGlobalExecutableTypes() {
        return globalExecutableTypes;
    }

    public void addBvalBinding(final @Observes BeforeBeanDiscovery beforeBeanDiscovery, final BeanManager beanManager) {
        beforeBeanDiscovery.addInterceptorBinding(BValBinding.class);
        beforeBeanDiscovery.addAnnotatedType(beanManager.createAnnotatedType(BValInterceptor.class));
    }

    // @WithAnnotations(ValidateOnExecution.class) doesn't check interfaces so not enough
    public <A> void processAnnotatedType(final @Observes ProcessAnnotatedType<A> pat) {
        if (!isExecutableValidationEnabled) {
            return;
        }
        final AnnotatedType<A> annotatedType = pat.getAnnotatedType();

        if (!annotatedTypeFilter.accept(annotatedType)) {
            return;
        }
        final Class<A> javaClass = annotatedType.getJavaClass();
        final int modifiers = javaClass.getModifiers();
        if (!javaClass.isInterface() && !javaClass.isAnonymousClass() && !Modifier.isFinal(modifiers) && !Modifier.isAbstract(modifiers)) {
            try {
                if (hasValidation(annotatedType)
                    || hasValidationAnnotation(annotatedType.getMethods())
                    || hasValidationAnnotation(annotatedType.getConstructors())
                    || Stream.concat(annotatedType.getMethods().stream(), annotatedType.getConstructors().stream())
                        .flatMap(it -> it.getParameters().stream())
                        .anyMatch(this::hasValidation)) {
                    pat.setAnnotatedType(new BValAnnotatedType<>(annotatedType));
                }
            } catch (final Exception e) {
                if (e instanceof ValidationException) {
                    throw e;
                }
                LOGGER.log(Level.INFO, e.getMessage());
            } catch (final NoClassDefFoundError ncdfe) {
                // skip
            }
        }
    }

    public <A> void processBean(final @Observes ProcessBean<A> processBeanEvent) {
        if (validatorFound && validatorFactoryFound) {
            return;
        }

        final Bean<A> bean = processBeanEvent.getBean();
        if (ValidatorBean.class.isInstance(bean) || ValidatorFactoryBean.class.isInstance(bean)) {
            return;
        }

        final Set<Type> types = bean.getTypes();
        if (!validatorFound) {
            validatorFound = types.contains(Validator.class);
        }
        if (!validatorFactoryFound) {
            validatorFactoryFound = types.contains(ValidatorFactory.class);
        }
    }

    public void addBValBeans(final @Observes AfterBeanDiscovery afterBeanDiscovery, final BeanManager beanManager) {
        if (factory != null && factory.optional().isPresent()) { // cleanup cache used to discover ValidateOnException before factory is recreated
            factory.get().close();
        }
        if (config instanceof ConfigurationImpl) {
            ((ConfigurationImpl) config).releaseDeferredBootstrapOverrides();
        }
        if (!validatorFactoryFound) {
            try { // recreate the factory
                factory = new Lazy<>(config::buildValidatorFactory);
                afterBeanDiscovery.addBean(new ValidatorFactoryBean(factory));
                validatorFactoryFound = true;
            } catch (final ValidationException ve) {
                //throw ve;
            } catch (final Exception e) { // can throw an exception with custom providers
                LOGGER.log(Level.SEVERE, e.getMessage(), e);
            }
        }
        if (!validatorFound && validatorFactoryFound) {
            try {
                afterBeanDiscovery.addBean(new ValidatorBean(() -> CDI.current().select(ValidatorFactory.class).get().getValidator()));
                validatorFound = true;
            } catch (final ValidationException ve) {
                throw ve;
            } catch (final Exception e) {
                LOGGER.log(Level.SEVERE, e.getMessage(), e);
            }
        }
    }

    public void afterStart(@Observes final AfterDeploymentValidation clearEvent) {
        potentiallyBValAnnotation.clear();
        notBValAnnotation.clear();
    }

    private boolean hasValidationAnnotation(final Collection<? extends Annotated> annotateds) {
        return annotateds.stream().anyMatch(this::hasValidation);
    }

    private boolean hasValidation(final Annotated m) {
        return m.getAnnotations().stream()
                .anyMatch(it -> {
                    final Class<? extends Annotation> type = it.annotationType();
                    if (type == ValidateOnExecution.class || type == Valid.class) {
                        return true;
                    }
                    if (isSkippedAnnotation(type)) {
                        return false;
                    }
                    if (type.getName().startsWith("javax.validation.constraints")) {
                        return true;
                    }
                    if (notBValAnnotation.contains(type)) { // more likely so faster first
                        return false;
                    }
                    if (potentiallyBValAnnotation.contains(type)) {
                        return true;
                    }
                    cacheIsBvalAnnotation(type);
                    return potentiallyBValAnnotation.contains(type);
                });
    }

    private boolean isSkippedAnnotation(final Class<? extends Annotation> type) {
        if (type.getName().startsWith("java.")) {
            return true;
        }
        if (type.getName().startsWith("javax.enterprise.")) {
            return true;
        }
        if (type.getName().startsWith("javax.inject.")) {
            return true;
        }
        return false;
    }

    private void cacheIsBvalAnnotation(final Class<? extends Annotation> type) {
        if (flattenAnnotations(type, new HashSet<>()).anyMatch(it -> it == Constraint.class)) {
            potentiallyBValAnnotation.add(type);
        } else {
            notBValAnnotation.add(type);
        }
    }

    private Stream<Class<?>> flattenAnnotations(final Class<? extends Annotation> type, final Set<Class<?>> seen) {
        seen.add(type);
        return Stream.of(type)
                     .flatMap(it -> Stream.concat(
                             Stream.of(it),
                             Stream.of(it.getAnnotations())
                                   .map(Annotation::annotationType)
                                   .distinct()
                                   .filter(a -> !isSkippedAnnotation(a))
                                   .filter(seen::add)
                                   .flatMap(a -> flattenAnnotations(a, seen))));
    }

    /**
     * Request that an instance of the specified type be provided by the container.
     * @param clazz
     * @return the requested instance wrapped in a {@link Releasable}.
     */
    public static <T> Releasable<T> inject(final Class<T> clazz) {
        try {
            final BeanManager beanManager = CDI.current().getBeanManager();
            if (beanManager == null) {
                return null;
            }
            final AnnotatedType<T> annotatedType = beanManager.createAnnotatedType(clazz);
            final InjectionTarget<T> it = beanManager.createInjectionTarget(annotatedType);
            final CreationalContext<T> context = beanManager.createCreationalContext(null);
            final T instance = it.produce(context);
            it.inject(instance, context);
            it.postConstruct(instance);

            return new Releasable<>(context, it, instance);
        } catch (final Exception | NoClassDefFoundError error) {
            // no-op
        }
        return null;
    }

    public static BeanManager getBeanManager() {
        return CDI.current().getBeanManager();
    }

    /**
     * Represents an item that can be released from a {@link CreationalContext} at some point in the future.
     * @param <T>
     */
    public static class Releasable<T> {
        private final CreationalContext<T> context;
        private final InjectionTarget<T> injectionTarget;
        private final T instance;

        private Releasable(final CreationalContext<T> context, final InjectionTarget<T> injectionTarget,
            final T instance) {
            this.context = context;
            this.injectionTarget = injectionTarget;
            this.instance = instance;
        }

        public void release() {
            try {
                injectionTarget.preDestroy(instance);
                injectionTarget.dispose(instance);
                context.release();
            } catch (final Exception | NoClassDefFoundError e) {
                // no-op
            }
        }

        public T getInstance() {
            return instance;
        }
    }

    /**
     * Defines an item that can determine whether a given {@link AnnotatedType} will be processed
     * by the {@link BValExtension} for executable validation. May be statically applied before
     * container startup.
     * @see BValExtension#setAnnotatedTypeFilter(AnnotatedTypeFilter)
     */
    public interface AnnotatedTypeFilter {
        boolean accept(AnnotatedType<?> annotatedType);
    }
}
