/*
 * 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.sling.i18n.impl;

import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.TreeMap;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
import org.apache.sling.commons.osgi.Order;
import org.apache.sling.commons.osgi.ServiceUtil;
import org.apache.sling.i18n.DefaultLocaleResolver;
import org.apache.sling.i18n.LocaleResolver;
import org.apache.sling.i18n.RequestLocaleResolver;
import org.apache.sling.i18n.ResourceBundleProvider;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>I18NFilter</code> class is a request level filter, which provides
 * the resource bundle for the current request.
 */
@Component(service = Filter.class,
    property = {
            Constants.SERVICE_DESCRIPTION + "=Internationalization Support Filter",
            Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
            Constants.SERVICE_RANKING + ":Integer=700",
            "sling.filter.scope=REQUEST",
            "sling.filter.scope=ERROR",
            HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN + "=/",
            HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT + "=(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=*)"
    })
public class I18NFilter implements Filter {

    /**
     * The default server default locale if not configured <code>Locale.ENGLISH</code>.
     */
    private static final Locale DEFAULT_LOCALE = Locale.ENGLISH;

    /** Logger */
    private final static Logger LOG = LoggerFactory.getLogger(I18NFilter.class.getName());

    private final DefaultLocaleResolver DEFAULT_LOCALE_RESOLVER = new DefaultLocaleResolver();

    private volatile LocaleResolver localeResolver = DEFAULT_LOCALE_RESOLVER;

    private volatile RequestLocaleResolver requestLocaleResolver = DEFAULT_LOCALE_RESOLVER;

    private final Map<Object, ResourceBundleProvider> providers = new TreeMap<>();

    private volatile ResourceBundleProvider[] sortedProviders = new ResourceBundleProvider[0];

    private final ResourceBundleProvider combinedProvider = new CombinedBundleProvider();

    /** Count the number init() has been called. */
    private volatile int initCount;

    /**
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    @Override
    public void init(FilterConfig filterConfig) {
        synchronized(this) {
            initCount++;
        }
    }

    /**
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    @Override
    public void doFilter(ServletRequest request,
                         final ServletResponse response,
                         final FilterChain chain)
    throws IOException, ServletException {
        final boolean runGlobal = this.initCount == 2;
        if ( request instanceof SlingHttpServletRequest ) {
            // check if we can use the simple version to wrap
            if ( !runGlobal || this.requestLocaleResolver == DEFAULT_LOCALE_RESOLVER ) {
                // wrap with our ResourceBundle provisioning
                request = new I18NSlingHttpServletRequest(request,
                        combinedProvider, localeResolver);
            } else {
                request = new BaseI18NSlingHttpServletRequest(request, combinedProvider);
            }
        } else {
            request = new I18NHttpServletRequest(request,
                    combinedProvider, requestLocaleResolver);
        }

        // and forward the request
        chain.doFilter(request, response);
    }

    /**
     * @see javax.servlet.Filter#destroy()
     */
    @Override
    public void destroy() {
        synchronized(this) {
            initCount--;
        }
    }

    // ---------- SCR Integration ----------------------------------------------

    @Reference(cardinality = ReferenceCardinality.OPTIONAL,
            policy = ReferencePolicy.DYNAMIC,
            policyOption=ReferencePolicyOption.GREEDY)
    protected void bindLocaleResolver(final LocaleResolver resolver) {
        this.localeResolver = resolver;
    }

    protected void unbindLocaleResolver(final LocaleResolver resolver) {
        if (this.localeResolver == resolver) {
            this.localeResolver = DEFAULT_LOCALE_RESOLVER;
        }
    }

    @Reference(cardinality = ReferenceCardinality.OPTIONAL,
            policy = ReferencePolicy.DYNAMIC,
            policyOption=ReferencePolicyOption.GREEDY)
    protected void bindRequestLocaleResolver(final RequestLocaleResolver resolver) {
        this.requestLocaleResolver = resolver;
    }

    protected void unbindRequestLocaleResolver(final RequestLocaleResolver resolver) {
        if (this.requestLocaleResolver == resolver) {
            this.requestLocaleResolver = DEFAULT_LOCALE_RESOLVER;
        }
    }

    @Reference(service = ResourceBundleProvider.class,
            cardinality = ReferenceCardinality.MULTIPLE,
            policy = ReferencePolicy.DYNAMIC)
    protected void bindResourceBundleProvider(final ResourceBundleProvider provider, final Map<String, Object> props) {
        synchronized ( this.providers ) {
            this.providers.put(ServiceUtil.getComparableForServiceRanking(props, Order.ASCENDING), provider);
            this.sortedProviders = this.providers.values().toArray(new ResourceBundleProvider[this.providers.size()]);
        }
    }

    protected void unbindResourceBundleProvider(final ResourceBundleProvider provider, final Map<String, Object> props) {
        synchronized ( this.providers ) {
            this.providers.remove(ServiceUtil.getComparableForServiceRanking(props, Order.ASCENDING));
            this.sortedProviders = this.providers.values().toArray(new ResourceBundleProvider[this.providers.size()]);
        }
    }

    // ---------- internal -----------------------------------------------------

    /** Provider that goes through a list of registered providers and takes the first non-null responses */
    private class CombinedBundleProvider implements ResourceBundleProvider {

        @Override
        public Locale getDefaultLocale() {
            // ask all registered providers, use the first one that returns
            final ResourceBundleProvider[] providers = sortedProviders;
            for(int i=providers.length-1; i >= 0; i--) {
                final ResourceBundleProvider provider = providers[i];
                final Locale locale = provider.getDefaultLocale();
                if (locale != null) {
                    return locale;
                }
            }
            return null;
        }

        @Override
        public ResourceBundle getResourceBundle(final Locale locale) {
            // ask all registered providers, use the first one that returns
            final ResourceBundleProvider[] providers = sortedProviders;
            for(int i=providers.length-1; i >= 0; i--) {
                final ResourceBundleProvider provider = providers[i];
                final ResourceBundle bundle = provider.getResourceBundle(locale);
                if (bundle != null) {
                    return bundle;
                }
            }
            return null;
        }

        @Override
        public ResourceBundle getResourceBundle(final String baseName, final Locale locale) {
            // ask all registered providers, use the first one that returns
            final ResourceBundleProvider[] providers = sortedProviders;
            for(int i=providers.length-1; i >= 0; i--) {
                final ResourceBundleProvider provider = providers[i];
                final ResourceBundle bundle = provider.getResourceBundle(baseName, locale);
                if (bundle != null) {
                    return bundle;
                }
            }
            return null;
        }
    }

    private static Locale defaultLocale(ResourceBundleProvider bundleProvider) {
        Locale defaultLocale = bundleProvider.getDefaultLocale();
        return (defaultLocale != null) ? defaultLocale : DEFAULT_LOCALE;
    }

    // ---------- internal class -----------------------------------------------

    private static class I18NHttpServletRequest
        extends HttpServletRequestWrapper {

        private final ResourceBundleProvider bundleProvider;

        private final RequestLocaleResolver localeResolver;

        private Locale locale;

        private List<Locale> localeList;

        private ResourceBundle resourceBundle;

        I18NHttpServletRequest(final ServletRequest delegatee,
                final ResourceBundleProvider bundleProvider,
                final RequestLocaleResolver localeResolver) {
            super((HttpServletRequest)delegatee);
            this.bundleProvider = bundleProvider;
            this.localeResolver = localeResolver;
        }

        @Override
        public Locale getLocale() {
            if (locale == null) {
                locale = this.getLocaleList().get(0);
            }

            return locale;
        }

        @Override
        public Enumeration<Locale> getLocales() {
            return Collections.enumeration(getLocaleList());
        }

        @Override
        public Object getAttribute(final String name) {
            if ( ResourceBundleProvider.BUNDLE_REQ_ATTR.equals(name) ) {
                if ( this.resourceBundle == null && this.bundleProvider != null) {
                    this.resourceBundle = this.bundleProvider.getResourceBundle(this.getLocale());
                }
                return this.resourceBundle;
            }
            return super.getAttribute(name);
        }

        private List<Locale> getLocaleList() {
            if (localeList == null) {
                List<Locale> resolved = localeResolver.resolveLocale((HttpServletRequest)this.getRequest());
                this.localeList = (resolved != null && !resolved.isEmpty())
                        ? resolved
                        : Collections.singletonList(defaultLocale(this.bundleProvider));
            }

            return localeList;
        }

    }

    private static class BaseI18NSlingHttpServletRequest
        extends SlingHttpServletRequestWrapper {

        protected final ResourceBundleProvider bundleProvider;

        BaseI18NSlingHttpServletRequest(final ServletRequest delegatee,
                final ResourceBundleProvider bundleProvider) {
            super((SlingHttpServletRequest) delegatee);
            this.bundleProvider = bundleProvider;
        }

        @Override
        public ResourceBundle getResourceBundle(Locale locale) {
            return getResourceBundle(null, locale);
        }

        @Override
        public ResourceBundle getResourceBundle(String baseName, Locale locale) {
            if (bundleProvider != null) {
                if (locale == null) {
                    locale = getLocale();
                }

                try {
                    return bundleProvider.getResourceBundle(baseName, locale);
                } catch (MissingResourceException mre) {
                    LOG.warn(
                        "getResourceBundle: Cannot get ResourceBundle from provider",
                        mre);
                }
            } else {
                LOG.info("getResourceBundle: ResourceBundleProvider not available, calling default implementation");
            }

            return super.getResourceBundle(baseName, locale);
        }
    }

    private static class I18NSlingHttpServletRequest
        extends BaseI18NSlingHttpServletRequest {

        private final LocaleResolver localeResolver;

        private Locale locale;

        private List<Locale> localeList;

        I18NSlingHttpServletRequest(final ServletRequest delegatee,
                final ResourceBundleProvider bundleProvider,
                final LocaleResolver localeResolver) {
            super(delegatee, bundleProvider);
            this.localeResolver = localeResolver;
        }

        @Override
        public Object getAttribute(final String name) {
            if ( ResourceBundleProvider.BUNDLE_REQ_ATTR.equals(name) ) {
                final Object superValue = super.getAttribute(name);
                return (superValue != null ? superValue : this.getResourceBundle(null));
            }
            return super.getAttribute(name);
        }

        @Override
        public Locale getLocale() {
            if (locale == null) {
                locale = this.getLocaleList().get(0);
            }

            return locale;
        }

        @Override
        public Enumeration<Locale> getLocales() {
            return Collections.enumeration(getLocaleList());
        }

        private List<Locale> getLocaleList() {
            if (localeList == null) {
                List<Locale> resolved = localeResolver.resolveLocale(this.getSlingRequest());
                this.localeList = (resolved != null && !resolved.isEmpty())
                        ? resolved
                        : Collections.singletonList(defaultLocale(this.bundleProvider));
            }

            return localeList;
        }
    }

}
