/*
 * 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.myfaces.extensions.validator.core;

import org.apache.myfaces.extensions.validator.core.factory.DefaultFactoryFinder;
import org.apache.myfaces.extensions.validator.core.factory.FactoryFinder;
import org.apache.myfaces.extensions.validator.core.initializer.component.ComponentInitializer;
import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfiguration;
import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationNames;
import org.apache.myfaces.extensions.validator.core.interceptor.MetaDataExtractionInterceptor;
import org.apache.myfaces.extensions.validator.core.interceptor.PropertyValidationInterceptor;
import org.apache.myfaces.extensions.validator.core.interceptor.RendererInterceptor;
import org.apache.myfaces.extensions.validator.core.interceptor.ValidationExceptionInterceptor;
import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
import org.apache.myfaces.extensions.validator.core.recorder.ProcessedInformationRecorder;
import org.apache.myfaces.extensions.validator.core.validation.SkipValidationEvaluator;
import org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverityInterpreter;
import org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy;
import org.apache.myfaces.extensions.validator.internal.UsageCategory;
import org.apache.myfaces.extensions.validator.internal.UsageInformation;
import org.apache.myfaces.extensions.validator.util.ClassUtils;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

import static org.apache.myfaces.extensions.validator.util.WebXmlUtils.getInitParameter;

/**
 * @since 1.x.1
 */
@UsageInformation(UsageCategory.API)
public class ExtValContext
{
    private final Logger logger = Logger.getLogger(getClass().getName());

    private static ExtValContext extValContext;

    //don't try to resolve it dynamically e.g. via InformationProviderBean - there's a mojarra issue
    private static final String CUSTOM_EXTVAL_CONTEXT_CLASS_NAME =
            ExtValContext.class.getName().replace(".core.", ".custom.");

    private static final String CUSTOM_EXTVAL_MODULE_CONFIGURATION_RESOLVER_CLASS_NAME =
            ExtValModuleConfigurationResolver.class.getName().replace(".core.", ".custom.");

    private ViolationSeverityInterpreter violationSeverityInterpreter;
    private FactoryFinder factoryFinder = DefaultFactoryFinder.getInstance();
    private Map<String, RendererInterceptor> rendererInterceptors =
            new ConcurrentHashMap<String, RendererInterceptor>();
    private List<String> deniedInterceptors = new CopyOnWriteArrayList<String>();
    private List<ProcessedInformationRecorder> processedInformationRecorders =
            new CopyOnWriteArrayList<ProcessedInformationRecorder>();

    private SkipValidationEvaluator skipValidationEvaluator;

    private List<RendererInterceptor> rendererInterceptorCache = null;

    private Map<String, Object> globalProperties = new HashMap<String, Object>();

    /**
     * Storage for all configuration objects.
     * @since r4
     */
    private Map<Class<? extends ExtValModuleConfiguration>, ExtValModuleConfiguration> extValConfig =
            new ConcurrentHashMap<Class<? extends ExtValModuleConfiguration>, ExtValModuleConfiguration>();

    /**
     * Configured Module Configuration resolver.
     * @since r4
     */
    private ExtValModuleConfigurationResolver defaultModuleConfigurationResolver;

    private Map<StaticConfigurationNames, List<StaticConfiguration<String, String>>> staticConfigMap
            = new HashMap<StaticConfigurationNames, List<StaticConfiguration<String, String>>>();

    private ExtValContextInternals contextHelper;
    private ExtValContextInvocationOrderAwareInternals invocationOrderAwareContextHelper;

    protected ExtValContext()
    {
        this.contextHelper = new ExtValContextInternals();
        this.invocationOrderAwareContextHelper = new ExtValContextInvocationOrderAwareInternals(this.contextHelper);

        retrieveModuleConfigurationResolver();
    }

    /**
     * Retrieves the Module Configuration Resolver.  Code looks first for a resolver located under the ExtVal Custom
     * package (org.apache.myfaces.extensions.validator.custom.ExtValModuleConfigurationResolver) and then for a
     * web.xml defined initialization parameter org.apache.myfaces.extensions.validator.core.
     * ExtValModuleConfigurationResolver
     * for a fully qualified class name.  The resolver configured by the web.xml overrides the custom defined one.
     */
    private void retrieveModuleConfigurationResolver()
    {
        Object customExtValModuleConfigurationResolver =
                ClassUtils.tryToInstantiateClassForName(CUSTOM_EXTVAL_MODULE_CONFIGURATION_RESOLVER_CLASS_NAME);

        if(customExtValModuleConfigurationResolver instanceof ExtValModuleConfigurationResolver)
        {
            this.defaultModuleConfigurationResolver =
                    (ExtValModuleConfigurationResolver)customExtValModuleConfigurationResolver;
        }

        String customExtValModuleConfigurationResolverClassName =
                getInitParameter(null, ExtValModuleConfigurationResolver.class.getName());

        if(customExtValModuleConfigurationResolverClassName != null)
        {
            customExtValModuleConfigurationResolver =
                    ClassUtils.tryToInstantiateClassForName(customExtValModuleConfigurationResolverClassName);

            if(customExtValModuleConfigurationResolver instanceof ExtValModuleConfigurationResolver)
            {
                this.defaultModuleConfigurationResolver =
                        (ExtValModuleConfigurationResolver)customExtValModuleConfigurationResolver;
            }
        }
    }

    public static ExtValContext getContext()
    {
        if (extValContext == null)
        {
            extValContext = new ExtValContext();

            tryToCreateCustomExtValContext();
        }
        return extValContext;
    }

    private static void tryToCreateCustomExtValContext()
    {
        Object customExtValContext = ClassUtils.tryToInstantiateClassForName(CUSTOM_EXTVAL_CONTEXT_CLASS_NAME);

        if (customExtValContext instanceof ExtValContext)
        {
            extValContext = (ExtValContext) customExtValContext;
        }
    }

    public void setViolationSeverityInterpreter(ViolationSeverityInterpreter violationSeverityInterpreter)
    {
        setViolationSeverityInterpreter(violationSeverityInterpreter, true);
    }

    public void setViolationSeverityInterpreter(
            ViolationSeverityInterpreter violationSeverityInterpreter, boolean forceOverride)
    {
        if (this.violationSeverityInterpreter == null || forceOverride)
        {
            if (violationSeverityInterpreter != null)
            {
                this.logger.info(violationSeverityInterpreter.getClass() + " is used");
            }
            this.violationSeverityInterpreter = violationSeverityInterpreter;
        }
    }

    public ViolationSeverityInterpreter getViolationSeverityInterpreter()
    {
        ViolationSeverityInterpreter requestScopedInterpreter = this.contextHelper
                .getRequestScopedViolationSeverityInterpreter();

        if(requestScopedInterpreter != null)
        {
            return requestScopedInterpreter;
        }

        return this.violationSeverityInterpreter;
    }

    /*
    * FactoryFinder
    */
    public FactoryFinder getFactoryFinder()
    {
        return this.factoryFinder;
    }

    public void setFactoryFinder(FactoryFinder factoryFinder)
    {
        if (factoryFinder != null)
        {
            this.factoryFinder = factoryFinder;
        }
    }

    /*
     * SkipValidationEvaluator
     */
    public void setSkipValidationEvaluator(SkipValidationEvaluator skipValidationEvaluator)
    {
        setSkipValidationEvaluator(skipValidationEvaluator, true);
    }

    public void setSkipValidationEvaluator(SkipValidationEvaluator skipValidationEvaluator, boolean forceOverride)
    {
        if (this.skipValidationEvaluator == null || forceOverride)
        {
            if (skipValidationEvaluator != null)
            {
                this.logger.info(skipValidationEvaluator.getClass() + " is used");
            }
            this.skipValidationEvaluator = skipValidationEvaluator;
        }
    }

    public SkipValidationEvaluator getSkipValidationEvaluator()
    {
        if (this.skipValidationEvaluator == null)
        {
            return new SkipValidationEvaluator()
            {
                public boolean skipValidation(FacesContext facesContext, UIComponent uiComponent,
                                              ValidationStrategy validationStrategy, MetaDataEntry entry)
                {
                    return false;
                }
            };
        }

        return this.skipValidationEvaluator;
    }

    /*
     * RendererInterceptors
     */
    public List<RendererInterceptor> getRendererInterceptors()
    {
        if (this.rendererInterceptorCache == null)
        {
            this.rendererInterceptorCache = new ArrayList<RendererInterceptor>(this.rendererInterceptors.values());
        }

        return this.rendererInterceptorCache;
    }

    public boolean registerRendererInterceptor(RendererInterceptor rendererInterceptor)
    {
        synchronized (ExtValContext.class)
        {
            if (this.deniedInterceptors.contains(rendererInterceptor.getInterceptorId()))
            {
                return false;
            }

            this.rendererInterceptors.put(rendererInterceptor.getInterceptorId(), rendererInterceptor);
            this.rendererInterceptorCache = new ArrayList<RendererInterceptor>(this.rendererInterceptors.values());
        }
        return true;
    }

    public void deregisterRendererInterceptor(Class<? extends RendererInterceptor> rendererInterceptorClass)
    {
        RendererInterceptor rendererInterceptor = ClassUtils.tryToInstantiateClass(rendererInterceptorClass);

        synchronized (ExtValContext.class)
        {
            this.rendererInterceptors.remove(rendererInterceptor.getInterceptorId());
            this.rendererInterceptorCache = new ArrayList<RendererInterceptor>(this.rendererInterceptors.values());
        }
    }

    //if an interceptor hasn't been registered so far, it should be denied at future registrations
    public void denyRendererInterceptor(Class<? extends RendererInterceptor> rendererInterceptorClass)
    {
        RendererInterceptor rendererInterceptor = ClassUtils.tryToInstantiateClass(rendererInterceptorClass);

        synchronized (ExtValContext.class)
        {
            if (!this.deniedInterceptors.contains(rendererInterceptor.getInterceptorId()))
            {
                this.deniedInterceptors.add(rendererInterceptor.getInterceptorId());
            }
        }
        deregisterRendererInterceptor(rendererInterceptorClass);
    }

    /*
     * ComponentInitializers
     */
    public void addComponentInitializer(ComponentInitializer componentInitializer)
    {
        this.invocationOrderAwareContextHelper.lazyInitComponentInitializers();
        this.invocationOrderAwareContextHelper.addComponentInitializer(componentInitializer);
    }

    public List<ComponentInitializer> getComponentInitializers()
    {
        this.invocationOrderAwareContextHelper.lazyInitComponentInitializers();
        return this.invocationOrderAwareContextHelper.getComponentInitializers();
    }

    /*
     * ValidationExceptionInterceptors
     */
    public void addValidationExceptionInterceptor(ValidationExceptionInterceptor validationExceptionInterceptor)
    {
        this.invocationOrderAwareContextHelper.lazyInitValidationExceptionInterceptors();
        this.invocationOrderAwareContextHelper.addValidationExceptionInterceptor(validationExceptionInterceptor);
    }

    public List<ValidationExceptionInterceptor> getValidationExceptionInterceptors()
    {
        this.invocationOrderAwareContextHelper.lazyInitValidationExceptionInterceptors();
        return this.invocationOrderAwareContextHelper.getValidationExceptionInterceptors();
    }

    /*
     * PropertyValidationInterceptors
     */
    public void addPropertyValidationInterceptor(PropertyValidationInterceptor propertyValidationInterceptor)
    {
        this.invocationOrderAwareContextHelper.lazyInitPropertyValidationInterceptors();
        this.invocationOrderAwareContextHelper.addPropertyValidationInterceptor(propertyValidationInterceptor);
    }

    /**
     * @return all global validation interceptors
     */
    public List<PropertyValidationInterceptor> getPropertyValidationInterceptors()
    {
        this.invocationOrderAwareContextHelper.lazyInitPropertyValidationInterceptors();
        return this.invocationOrderAwareContextHelper.getPropertyValidationInterceptors();
    }

    public List<PropertyValidationInterceptor> getPropertyValidationInterceptorsFor(Class moduleKey)
    {
        this.invocationOrderAwareContextHelper.lazyInitPropertyValidationInterceptors();
        return this.invocationOrderAwareContextHelper.getPropertyValidationInterceptorsFor(moduleKey);
    }

    /*
     * MetaDataExtractionInterceptors
     */
    public void addMetaDataExtractionInterceptor(MetaDataExtractionInterceptor metaDataExtractionInterceptor)
    {
        this.invocationOrderAwareContextHelper.lazyInitMetaDataExtractionInterceptors();
        this.invocationOrderAwareContextHelper.addMetaDataExtractionInterceptor(metaDataExtractionInterceptor);
    }

    /**
     * @return all global meta-data extraction interceptors
     */
    public List<MetaDataExtractionInterceptor> getMetaDataExtractionInterceptors()
    {
        this.invocationOrderAwareContextHelper.lazyInitMetaDataExtractionInterceptors();
        return this.invocationOrderAwareContextHelper.getMetaDataExtractionInterceptors();
    }

    public List<MetaDataExtractionInterceptor> getMetaDataExtractionInterceptorsFor(Class moduleKey)
    {
        Map<String, Object> properties = new HashMap<String, Object>();

        if(moduleKey != null)
        {
            properties.put(ValidationModuleKey.class.getName(), moduleKey);
        }
        return getMetaDataExtractionInterceptorsWith(properties);
    }

    public List<MetaDataExtractionInterceptor> getMetaDataExtractionInterceptorsWith(Map<String, Object> properties)
    {
        this.invocationOrderAwareContextHelper.lazyInitMetaDataExtractionInterceptors();
        return this.invocationOrderAwareContextHelper.getMetaDataExtractionInterceptorsWith(properties);
    }

    /*
     * ProcessedInformationRecorders
     */
    public List<ProcessedInformationRecorder> getProcessedInformationRecorders()
    {
        return this.processedInformationRecorders;
    }

    public void addProcessedInformationRecorder(ProcessedInformationRecorder processedInformationRecorder)
    {
        this.processedInformationRecorders.add(processedInformationRecorder);
    }

    /*
     * InformationProviderBean
     */
    public InformationProviderBean getInformationProviderBean()
    {
        return this.contextHelper.getInformationProviderBean();
    }

    /*
     * StaticConfiguration
     */
    public List<StaticConfiguration<String, String>> getStaticConfiguration(StaticConfigurationNames name)
    {
        if (!this.staticConfigMap.containsKey(name))
        {
            List<StaticConfiguration<String, String>> staticConfigList =
                    new ArrayList<StaticConfiguration<String, String>>();
            this.staticConfigMap.put(name, staticConfigList);
        }
        return this.staticConfigMap.get(name);
    }

    public void addStaticConfiguration(StaticConfigurationNames name, StaticConfiguration<String, String> staticConfig)
    {
        synchronized (this)
        {
            List<StaticConfiguration<String, String>> staticConfigList;
            if (!this.staticConfigMap.containsKey(name))
            {
                staticConfigList = new ArrayList<StaticConfiguration<String, String>>();
                this.staticConfigMap.put(name, staticConfigList);
            }
            this.staticConfigMap.get(name).add(staticConfig);
        }
    }

    /*
     * Global properties
     */
    public boolean addGlobalProperty(String name, Object value)
    {
        return addGlobalProperty(name, value, true);
    }

    public boolean addGlobalProperty(String name, Object value, boolean forceOverride)
    {
        if (this.globalProperties.containsKey(name))
        {
            if (!forceOverride)
            {
                return false;
            }

            this.logger.info("override global property '" + name + "'");
        }

        if(JsfProjectStage.is(JsfProjectStage.Development))
        {
            this.logger.info("global property [" + name + "] added");
        }

        this.globalProperties.put(name, value);
        return true;
    }

    public Object getGlobalProperty(String name)
    {
        return this.globalProperties.get(name);
    }

    /**
     * Retrieves the configuration object of the type specified by the parameter 'targetType'.  The type should be
     * direct descendants of ExtValModuleConfiguration and the same as the type you used to register the configuration
     * (see addModuleConfiguration).
     *
     * @param targetType Key that specifies the type of configuration, should be direct descendants of
     * ExtValModuleConfiguration
     * @param <T>
     * @return  configuration object
     * @since r4
     */
    public <T extends ExtValModuleConfiguration> T getModuleConfiguration(Class<T> targetType)
    {
        ExtValModuleConfiguration result = this.extValConfig.get(targetType);

        //noinspection unchecked
        return (T)result;
    }

    /**
     * Registers the configuration object specified in the parameter 'config' for the type 'key' within ExtVal
     * overriding
     * possible another registration.
     *
     * @param key Key that specifies the type of configuration, should be direct descendants of
     * ExtValModuleConfiguration
     * @param extValConfig Configuration object to register
     * @return true
     * @since r4
     */
    public boolean addModuleConfiguration(Class<? extends ExtValModuleConfiguration> key,
                                          ExtValModuleConfiguration extValConfig)
    {
        return addModuleConfiguration(key, extValConfig, true);
    }

    /**
     * Registers the configuration object specified in the parameter 'config' for the type 'key' within ExtVal.  When a
     * configuration object already exist for the key and we don't specify to override it (parameter forceOverride) the
     * configuration isn't registered.
     * @param key Key that specifies the type of configuration, should be direct descendants of
     * ExtValModuleConfiguration
     * @param config Configuration object to register
     * @param forceOverride Do we override another custom configuration that is already registered.
     * @return true is the configuration is registered or false if already existed and no ofrce override specified.
     * @since r4
     */
    public boolean addModuleConfiguration(Class<? extends ExtValModuleConfiguration> key,
                                          ExtValModuleConfiguration config,
                                          boolean forceOverride)
    {
        // Check if it already exists.
        if (this.extValConfig.containsKey(key))
        {
            if (!forceOverride)
            {
                // Don't forced, so not registered
                return false;
            }

            this.logger.info("override config for key '" + config.getClass() + "'");
        }

        //anonymous class are only supported for test-cases and
        //there we don't need a custom config defined in the web.xml
        // or from a resolver
        if(!config.getClass().isAnonymousClass())
        {
            config = tryToLoadCustomConfigImplementation(config);
        }

        // Store the configuration
        this.extValConfig.put(key, config);

        // Logging when in Development Stage.
        if(JsfProjectStage.is(JsfProjectStage.Development))
        {
            this.logger.info("config for key [" + config.getClass() + "] added");
        }

        return true;
    }

    /**
     * Tries to load a custom configuration implementation by looking for a web.xml initialization parameter. The method
     * returns the configuration object that should be used. That is, the custom defined version or the specified
     * as parameter of the method.
     *
     * @param config The configuration object for which we try to load another version
     * @return The custom configuration object or parameter specified if no alternative found.
     * @since r4
     */
    private ExtValModuleConfiguration tryToLoadCustomConfigImplementation(ExtValModuleConfiguration config)
    {
        // Get the parent if the parameter.  For the default version, like DefaultExtValCoreConfiguration, it is
        // the abstract base class.
        Class configClass = config.getClass().getSuperclass();

        // To be on the safe side that the parent still belongs to the configuration part of ExtVal.
        if(!ExtValModuleConfiguration.class.isAssignableFrom(configClass))
        {
            return config;
        }

        @SuppressWarnings({"unchecked"})
        Class<? extends ExtValModuleConfiguration> configDefinitionClass =
                (Class<? extends  ExtValModuleConfiguration>)configClass;

        // If we have a resolver, use it to retrieve the configuration
        if(this.defaultModuleConfigurationResolver != null)
        {
            config = this.defaultModuleConfigurationResolver.getCustomConfiguration(configDefinitionClass);
        }

        // Lookup the web.xml initialization parameter
        String customConfigClassName = getInitParameter(null, configDefinitionClass.getName());

        if(customConfigClassName != null)
        {
            // If specified, see if it exists and can be used.
            Object customConfig = ClassUtils.tryToInstantiateClassForName(customConfigClassName);

            if(customConfig instanceof ExtValModuleConfiguration)
            {
                return (ExtValModuleConfiguration)customConfig;
            }
        }
        // return the parameter or resolver one.
        return config;
    }
}
