/*
 * 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;
        }
    }

    /**
     * {@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 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);
    }
}
