/*
 * 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.io.InputStream;
import java.time.Clock;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;

import javax.validation.BootstrapConfiguration;
import javax.validation.ClockProvider;
import javax.validation.ConstraintValidatorFactory;
import javax.validation.MessageInterpolator;
import javax.validation.ParameterNameProvider;
import javax.validation.TraversableResolver;
import javax.validation.ValidationException;
import javax.validation.ValidationProviderResolver;
import javax.validation.ValidatorFactory;
import javax.validation.spi.BootstrapState;
import javax.validation.spi.ConfigurationState;
import javax.validation.spi.ValidationProvider;
import javax.validation.valueextraction.ValueExtractor;

import org.apache.bval.jsr.parameter.DefaultParameterNameProvider;
import org.apache.bval.jsr.resolver.DefaultTraversableResolver;
import org.apache.bval.jsr.util.IOs;
import org.apache.bval.jsr.valueextraction.ValueExtractors;
import org.apache.bval.jsr.xml.ValidationParser;
import org.apache.bval.util.CloseableAble;
import org.apache.bval.util.Exceptions;
import org.apache.bval.util.Lazy;
import org.apache.bval.util.reflection.Reflection;
import org.apache.commons.weaver.privilizer.Privileged;

/**
 * Description: used to configure apache-validation for jsr.
 * Implementation of Configuration that also implements ConfigurationState,
 * hence this can be passed to buildValidatorFactory(ConfigurationState).
 * <br/>
 */
public class ConfigurationImpl implements ApacheValidatorConfiguration, ConfigurationState, CloseableAble {

    private class LazyParticipant<T> extends Lazy<T> {
        private boolean locked;

        private LazyParticipant(Supplier<T> init) {
            super(init);
        }

        ConfigurationImpl override(T value) {
            if (value != null) {
                synchronized (this) {
                    if (!locked) {
                        try {
                            reset(() -> value);
                        } finally {
                            ConfigurationImpl.this.prepared = false;
                        }
                    }
                }
            }
            return ConfigurationImpl.this;
        }

        synchronized ConfigurationImpl externalOverride(T value) {
            locked = false;
            try {
                return override(value);
            } finally {
                locked = true;
            }
        }
    }

    /**
     * Configured {@link ValidationProvider}
     */
    //couldn't this be parameterized <ApacheValidatorConfiguration> or <? super ApacheValidatorConfiguration>?
    private final ValidationProvider<ApacheValidatorConfiguration> provider;

    /**
     * Configured {@link ValidationProviderResolver}
     */
    private final ValidationProviderResolver providerResolver;

    /**
     * Configured {@link ValidationProvider} class
     */
    private Class<? extends ValidationProvider<?>> providerClass;

    private final MessageInterpolator defaultMessageInterpolator = new DefaultMessageInterpolator();

    private final LazyParticipant<MessageInterpolator> messageInterpolator =
        new LazyParticipant<>(this::getDefaultMessageInterpolator);

    private final ConstraintValidatorFactory defaultConstraintValidatorFactory =
        new DefaultConstraintValidatorFactory();

    private final LazyParticipant<ConstraintValidatorFactory> constraintValidatorFactory =
        new LazyParticipant<>(this::getDefaultConstraintValidatorFactory);

    private final TraversableResolver defaultTraversableResolver = new DefaultTraversableResolver();

    private final LazyParticipant<TraversableResolver> traversableResolver =
        new LazyParticipant<>(this::getDefaultTraversableResolver);

    private final ParameterNameProvider defaultParameterNameProvider = new DefaultParameterNameProvider();

    private final LazyParticipant<ParameterNameProvider> parameterNameProvider =
        new LazyParticipant<>(this::getDefaultParameterNameProvider);

    private final ClockProvider defaultClockProvider = Clock::systemDefaultZone;

    private final LazyParticipant<ClockProvider> clockProvider = new LazyParticipant<>(this::getDefaultClockProvider);

    private final ValueExtractors bootstrapValueExtractors = ValueExtractors.EMPTY.createChild();
    private final ValueExtractors valueExtractors = bootstrapValueExtractors.createChild();

    private final Lazy<BootstrapConfiguration> bootstrapConfiguration = new Lazy<>(this::createBootstrapConfiguration);

    private final Set<InputStream> mappingStreams = new HashSet<>();
    private final Map<String, String> properties = new HashMap<>();

    private boolean beforeCdi = false;
    private ClassLoader loader;

    // BEGIN DEFAULTS
    /**
     * false = dirty flag (to prevent from multiple parsing validation.xml)
     */
    private boolean prepared = false;
    // END DEFAULTS

    private boolean ignoreXmlConfiguration = false;

    private ParticipantFactory participantFactory;
    private ValidationParser validationParser;

    /**
     * Create a new ConfigurationImpl instance.
     * @param aState bootstrap state
     * @param aProvider provider
     */
    public ConfigurationImpl(BootstrapState aState, ValidationProvider<ApacheValidatorConfiguration> aProvider) {
        Exceptions.raiseIf(aProvider == null && aState == null, ValidationException::new,
            "one of provider or state is required");

        if (aProvider == null) {
            this.provider = null;
            if (aState.getValidationProviderResolver() == null) {
                providerResolver = aState.getDefaultValidationProviderResolver();
            } else {
                providerResolver = aState.getValidationProviderResolver();
            }
        } else {
            this.provider = aProvider;
            this.providerResolver = null;
        }
        initializePropertyDefaults();
    }

    /**
     * {@inheritDoc}
     * Ignore data from the <i>META-INF/validation.xml</i> file if this
     * method is called.
     *
     * @return this
     */
    @Override
    public ApacheValidatorConfiguration ignoreXmlConfiguration() {
        ignoreXmlConfiguration = true;
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ConfigurationImpl messageInterpolator(MessageInterpolator resolver) {
        return messageInterpolator.externalOverride(resolver);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ApacheValidatorConfiguration traversableResolver(TraversableResolver resolver) {
        return traversableResolver.externalOverride(resolver);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ConfigurationImpl constraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
        return this.constraintValidatorFactory.externalOverride(constraintValidatorFactory);
    }

    @Override
    public ApacheValidatorConfiguration parameterNameProvider(ParameterNameProvider parameterNameProvider) {
        return this.parameterNameProvider.externalOverride(parameterNameProvider);
    }

    @Override
    public ApacheValidatorConfiguration clockProvider(ClockProvider clockProvider) {
        return this.clockProvider.externalOverride(clockProvider);
    }

    /**
     * {@inheritDoc}
     * Add a stream describing constraint mapping in the Bean Validation
     * XML format.
     *
     * @return this
     */
    @Override
    public ApacheValidatorConfiguration addMapping(InputStream stream) {
        if (stream != null) {
            mappingStreams.add(IOs.convertToMarkableInputStream(stream));
        }
        return this;
    }

    /**
     * {@inheritDoc}
     * Add a provider specific property. This property is equivalent to
     * XML configuration properties.
     * If we do not know how to handle the property, we silently ignore it.
     *
     * @return this
     */
    @Override
    public ApacheValidatorConfiguration addProperty(String name, String value) {
        properties.put(name, value);
        return this;
    }

    @Override
    public MessageInterpolator getDefaultMessageInterpolator() {
        return defaultMessageInterpolator;
    }

    @Override
    public TraversableResolver getDefaultTraversableResolver() {
        return defaultTraversableResolver;
    }

    @Override
    public ConstraintValidatorFactory getDefaultConstraintValidatorFactory() {
        return defaultConstraintValidatorFactory;
    }

    @Override
    public ParameterNameProvider getDefaultParameterNameProvider() {
        return defaultParameterNameProvider;
    }

    @Override
    public ClockProvider getDefaultClockProvider() {
        return defaultClockProvider;
    }

    /**
     * {@inheritDoc}
     * Return a map of non type-safe custom properties.
     *
     * @return null
     */
    @Override
    public Map<String, String> getProperties() {
        return properties;
    }

    /**
     * {@inheritDoc}
     * Returns true if Configuration.ignoreXMLConfiguration() has been called.
     * In this case, we ignore META-INF/validation.xml
     *
     * @return true
     */
    @Override
    public boolean isIgnoreXmlConfiguration() {
        return ignoreXmlConfiguration;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set<InputStream> getMappingStreams() {
        return mappingStreams;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public MessageInterpolator getMessageInterpolator() {
        return messageInterpolator.get();
    }

    @Override
    public BootstrapConfiguration getBootstrapConfiguration() {
        return bootstrapConfiguration.get();
    }

    /**
     * {@inheritDoc}
     * main factory method to build a ValidatorFactory
     *
     * @throws ValidationException if the ValidatorFactory cannot be built
     */
    @Override
    public ValidatorFactory buildValidatorFactory() {
        return doBuildValidatorFactory();
    }

    /**
     * {@inheritDoc}
     * @return the constraint validator factory of this configuration.
     */
    @Override
    public ConstraintValidatorFactory getConstraintValidatorFactory() {
        return constraintValidatorFactory.get();
    }

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

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

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

    @Override
    public ApacheValidatorConfiguration addValueExtractor(ValueExtractor<?> extractor) {
        valueExtractors.add(extractor);
        return this;
    }

    @Override
    public Set<ValueExtractor<?>> getValueExtractors() {
        return Collections.unmodifiableSet(new LinkedHashSet<>(valueExtractors.getValueExtractors().values()));
    }

    public void deferBootstrapOverrides() {
        beforeCdi = true;
    }

    public void releaseDeferredBootstrapOverrides() {
        if (beforeCdi) {
            beforeCdi = false;
            performBootstrapOverrides();
        }
    }

    @Override
    public Closeable getCloseable() {
        if (participantFactory == null) {
            return () -> {
            };
        }
        return participantFactory;
    }

    @Privileged
    private ValidatorFactory doBuildValidatorFactory() {
        prepare();
        return Optional.<ValidationProvider<?>> ofNullable(provider).orElseGet(this::findProvider)
            .buildValidatorFactory(this);
    }

    private void prepare() {
        if (!prepared) {
            applyBootstrapConfiguration();
            prepared = true;
        }
    }

    private BootstrapConfiguration createBootstrapConfiguration() {
        try {
            if (!ignoreXmlConfiguration) {
                loader = Reflection.loaderFromThreadOrClass(ValidationParser.class);
                validationParser = new ValidationParser(loader);
                final BootstrapConfiguration xmlBootstrap =
                    validationParser.processValidationConfig(getProperties().get(Properties.VALIDATION_XML_PATH), this);
                if (xmlBootstrap != null) {
                    return xmlBootstrap;
                }
            }
            validationParser =
                new ValidationParser(loader = Reflection.loaderFromThreadOrClass(ApacheValidatorFactory.class));

            return BootstrapConfigurationImpl.DEFAULT;
        } finally {
            participantFactory = new ParticipantFactory(loader);
        }
    }

    private void applyBootstrapConfiguration() {
        final BootstrapConfiguration bootstrapConfig = bootstrapConfiguration.get();

        if (bootstrapConfig.getDefaultProviderClassName() != null) {
            this.providerClass = loadClass(bootstrapConfig.getDefaultProviderClassName());
        }
        bootstrapConfig.getProperties().forEach(this::addProperty);
        bootstrapConfig.getConstraintMappingResourcePaths().stream().map(validationParser::open)
            .forEach(this::addMapping);

        if (!beforeCdi) {
            performBootstrapOverrides();
        }
    }

    private void performBootstrapOverrides() {
        final BootstrapConfiguration bootstrapConfig = bootstrapConfiguration.get();
        override(messageInterpolator, bootstrapConfig::getMessageInterpolatorClassName);
        override(traversableResolver, bootstrapConfig::getTraversableResolverClassName);
        override(constraintValidatorFactory, bootstrapConfig::getConstraintValidatorFactoryClassName);
        override(parameterNameProvider, bootstrapConfig::getParameterNameProviderClassName);
        override(clockProvider, bootstrapConfig::getClockProviderClassName);

        bootstrapConfig.getValueExtractorClassNames().stream().<ValueExtractor<?>> map(participantFactory::create)
            .forEach(bootstrapValueExtractors::add);
    }

    @SuppressWarnings("unchecked")
    private <T> Class<T> loadClass(final String className) {
        try {
            return (Class<T>) Class.forName(className, true, loader);
        } catch (final ClassNotFoundException ex) {
            throw new ValidationException(ex);
        }
    }

    private void initializePropertyDefaults() {
        properties.put(Properties.CONSTRAINTS_CACHE_SIZE, Integer.toString(50));
    }

    private ValidationProvider<?> findProvider() {
        if (providerClass == null) {
            return providerResolver.getValidationProviders().get(0);
        }
        final Optional<ValidationProvider<?>> knownProvider =
            providerResolver.getValidationProviders().stream().filter(providerClass::isInstance).findFirst();
        if (knownProvider.isPresent()) {
            return knownProvider.get();
        }
        try {
            return providerClass.getConstructor().newInstance();
        } catch (Exception e) {
            throw Exceptions.create(ValidationException::new, "Unable to find/create %s of type %s",
                ValidationProvider.class.getSimpleName(), providerClass);
        }
    }

    private <T> void override(LazyParticipant<T> participant, Supplier<String> getClassName) {
        Optional.ofNullable(getClassName.get()).<T> map(participantFactory::create).ifPresent(participant::override);
    }
}
