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

import java.io.Closeable;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;

import javax.validation.ClockProvider;
import javax.validation.ConstraintValidatorFactory;
import javax.validation.MessageInterpolator;
import javax.validation.ParameterNameProvider;
import javax.validation.TraversableResolver;
import javax.validation.Validation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.spi.ConfigurationState;
import javax.validation.valueextraction.ValueExtractor;

import org.apache.bval.jsr.descriptor.DescriptorManager;
import org.apache.bval.jsr.groups.GroupsComputer;
import org.apache.bval.jsr.metadata.MetadataBuilder;
import org.apache.bval.jsr.metadata.MetadataBuilder.ForBean;
import org.apache.bval.jsr.metadata.MetadataBuilders;
import org.apache.bval.jsr.metadata.MetadataSource;
import org.apache.bval.jsr.util.AnnotationsManager;
import org.apache.bval.jsr.valueextraction.ValueExtractors;
import org.apache.bval.jsr.valueextraction.ValueExtractors.OnDuplicateContainerElementKey;
import org.apache.bval.util.CloseableAble;
import org.apache.bval.util.reflection.Reflection;
import org.apache.commons.weaver.privilizer.Privilizing;
import org.apache.commons.weaver.privilizer.Privilizing.CallTo;

/**
 * Description: a factory is a complete configurated object that can create
 * validators.<br/>
 * This instance is not thread-safe.<br/>
 */
@Privilizing(@CallTo(Reflection.class))
public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {

    private static volatile ApacheValidatorFactory DEFAULT_FACTORY;

    /**
     * Convenience method to retrieve a default global ApacheValidatorFactory
     *
     * @return {@link ApacheValidatorFactory}
     */
    public static ApacheValidatorFactory getDefault() {
        if (DEFAULT_FACTORY == null) {
            synchronized (ApacheValidatorFactory.class) {
                if (DEFAULT_FACTORY == null) {
                    DEFAULT_FACTORY = Validation.byProvider(ApacheValidationProvider.class).configure()
                        .buildValidatorFactory().unwrap(ApacheValidatorFactory.class);
                }
            }
        }
        return DEFAULT_FACTORY;
    }

    /**
     * Set a particular {@link ApacheValidatorFactory} instance as the default.
     *
     * @param aDefaultFactory
     */
    public static void setDefault(ApacheValidatorFactory aDefaultFactory) {
        DEFAULT_FACTORY = aDefaultFactory;
    }

    private static ValueExtractors createBaseValueExtractors(ParticipantFactory participantFactory) {
        final ValueExtractors result = new ValueExtractors(OnDuplicateContainerElementKey.OVERWRITE);
        participantFactory.loadServices(ValueExtractor.class).forEach(result::add);
        return result;
    }

    private final Map<String, String> properties;
    private final AnnotationsManager annotationsManager;
    private final DescriptorManager descriptorManager = new DescriptorManager(this);
    private final MetadataBuilders metadataBuilders = new MetadataBuilders();
    private final ConstraintCached constraintsCache = new ConstraintCached();
    private final Map<Class<?>, Class<?>> unwrappedClassCache = new ConcurrentHashMap<>();
    private final Collection<Closeable> toClose = new ArrayList<>();
    private final GroupsComputer groupsComputer = new GroupsComputer();
    private final ParticipantFactory participantFactory;
    private final ValueExtractors valueExtractors;

    private MessageInterpolator messageResolver;
    private TraversableResolver traversableResolver;
    private ConstraintValidatorFactory constraintValidatorFactory;
    private ParameterNameProvider parameterNameProvider;
    private ClockProvider clockProvider;

    /**
     * Create a new ApacheValidatorFactory instance.
     */
    public ApacheValidatorFactory(ConfigurationState configuration) {
        properties = new HashMap<>(configuration.getProperties());
        parameterNameProvider = configuration.getParameterNameProvider();
        messageResolver = configuration.getMessageInterpolator();
        traversableResolver = configuration.getTraversableResolver();
        constraintValidatorFactory = configuration.getConstraintValidatorFactory();
        clockProvider = configuration.getClockProvider();

        if (configuration instanceof CloseableAble) {
            toClose.add(((CloseableAble) configuration).getCloseable());
        }
        participantFactory = new ParticipantFactory(Thread.currentThread().getContextClassLoader(),
            ApacheValidatorFactory.class.getClassLoader());

        toClose.add(participantFactory);

        valueExtractors = createBaseValueExtractors(participantFactory).createChild();
        configuration.getValueExtractors().forEach(valueExtractors::add);

        annotationsManager = new AnnotationsManager(this);
        loadAndVerifyUserCustomizations(configuration);
    }

    public Map<Class<?>, Class<?>> getUnwrappedClassCache() {
        return unwrappedClassCache;
    }

    /**
     * Get the property map of this {@link ApacheValidatorFactory}.
     *
     * @return Map<String, String>
     */
    public Map<String, String> getProperties() {
        return properties;
    }

    /**
     * Shortcut method to create a new Validator instance with factory's settings
     *
     * @return the new validator instance
     */
    @Override
    public Validator getValidator() {
        return usingContext().getValidator();
    }

    /**
     * {@inheritDoc}
     *
     * @return the validator factory's context
     */
    @Override
    public ApacheFactoryContext usingContext() {
        return new ApacheFactoryContext(this);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized ApacheValidatorFactory clone() {
        try {
            return (ApacheValidatorFactory) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(); // VM bug.
        }
    }

    /**
     * Set the {@link MessageInterpolator} used.
     *
     * @param messageResolver
     */
    public final void setMessageInterpolator(MessageInterpolator messageResolver) {
        if (messageResolver != null) {
            this.messageResolver = messageResolver;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public MessageInterpolator getMessageInterpolator() {
        return messageResolver;
    }

    /**
     * Set the {@link TraversableResolver} used.
     *
     * @param traversableResolver
     */
    public final void setTraversableResolver(TraversableResolver traversableResolver) {
        if (traversableResolver != null) {
            this.traversableResolver = traversableResolver;
        }
    }

    public void setParameterNameProvider(final ParameterNameProvider parameterNameProvider) {
        if (parameterNameProvider != null) {
            this.parameterNameProvider = parameterNameProvider;
        }
    }

    public void setClockProvider(final ClockProvider clockProvider) {
        if (clockProvider != null) {
            this.clockProvider = clockProvider;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public TraversableResolver getTraversableResolver() {
        return traversableResolver;
    }

    /**
     * Set the {@link ConstraintValidatorFactory} used.
     *
     * @param constraintValidatorFactory
     */
    public final void setConstraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
        if (constraintValidatorFactory != null) {
            this.constraintValidatorFactory = constraintValidatorFactory;
            if (DefaultConstraintValidatorFactory.class.isInstance(constraintValidatorFactory)) {
                toClose.add(Closeable.class.cast(constraintValidatorFactory));
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ConstraintValidatorFactory getConstraintValidatorFactory() {
        return constraintValidatorFactory;
    }

    @Override
    public ParameterNameProvider getParameterNameProvider() {
        return parameterNameProvider;
    }

    @Override
    public ClockProvider getClockProvider() {
        return clockProvider;
    }

    @Override
    public void close() {
        try {
            for (final Closeable c : toClose) {
                c.close();
            }
            toClose.clear();
        } catch (final Exception e) {
            // no-op
        }
    }

    /**
     * Return an object of the specified type to allow access to the provider-specific API. If the Bean Validation
     * provider implementation does not support the specified class, the ValidationException is thrown.
     *
     * @param type
     *            the class of the object to be returned.
     * @return an instance of the specified class
     * @throws ValidationException
     *             if the provider does not support the call.
     */
    @Override
    public <T> T unwrap(final Class<T> type) {
        if (type.isInstance(this)) {
            @SuppressWarnings("unchecked")
            final T result = (T) this;
            return result;
        }

        // FIXME 2011-03-27 jw:
        // This code is unsecure.
        // It should allow only a fixed set of classes.
        // Can't fix this because don't know which classes this method should support.

        if (!(type.isInterface() || Modifier.isAbstract(type.getModifiers()))) {
            return newInstance(type);
        }
        try {
            final Class<?> cls = Reflection.toClass(type.getName() + "Impl");
            if (type.isAssignableFrom(cls)) {
                @SuppressWarnings("unchecked")
                T result = (T) newInstance(cls);
                return result;
            }
        } catch (ClassNotFoundException e) {
            // do nothing
        }
        throw new ValidationException("Type " + type + " not supported");
    }

    private <T> T newInstance(final Class<T> cls) {
        try {
            return Reflection.newInstance(cls);
        } catch (final RuntimeException e) {
            throw new ValidationException(e.getCause());
        }
    }

    /**
     * Get the constraint cache used.
     *
     * @return {@link ConstraintCached}
     */
    public ConstraintCached getConstraintsCache() {
        return constraintsCache;
    }

    /**
     * Get the {@link AnnotationsManager}.
     * 
     * @return {@link AnnotationsManager}
     */
    public AnnotationsManager getAnnotationsManager() {
        return annotationsManager;
    }

    /**
     * Get the {@link DescriptorManager}.
     * 
     * @return {@link DescriptorManager}
     */
    public DescriptorManager getDescriptorManager() {
        return descriptorManager;
    }

    /**
     * Get the {@link ValueExtractors}.
     * 
     * @return {@link ValueExtractors}
     */
    public ValueExtractors getValueExtractors() {
        return valueExtractors;
    }

    public MetadataBuilders getMetadataBuilders() {
        return metadataBuilders;
    }

    public GroupsComputer getGroupsComputer() {
        return groupsComputer;
    }

    private void loadAndVerifyUserCustomizations(ConfigurationState configuration) {
        @SuppressWarnings({ "unchecked", "rawtypes" })
        final BiConsumer<Class<?>, ForBean<?>> addBuilder = (t, b) -> {
            getMetadataBuilders().registerCustomBuilder((Class) t, (MetadataBuilder.ForBean) b);
        };
        participantFactory.loadServices(MetadataSource.class)
            .forEach(ms -> {
                ms.initialize(this);
                ms.process(configuration, getConstraintsCache()::add, addBuilder);
            });
    }
}
