/*
 * 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 static org.apache.sling.i18n.impl.JcrResourceBundle.PROP_BASENAME;
import static org.apache.sling.i18n.impl.JcrResourceBundle.PROP_LANGUAGE;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.resource.observation.ExternalResourceChangeListener;
import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.observation.ResourceChangeListener;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.apache.sling.commons.scheduler.ScheduleOptions;
import org.apache.sling.commons.scheduler.Scheduler;
import org.apache.sling.i18n.ResourceBundleProvider;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>JcrResourceBundleProvider</code> implements the
 * <code>ResourceBundleProvider</code> interface creating
 * <code>ResourceBundle</code> instances from resources stored in the
 * repository.
 */
@Component(immediate = true, metatype = true, label = "%provider.name", description = "%provider.description")
@Service({ResourceBundleProvider.class, ResourceChangeListener.class})
@Property(name=ResourceChangeListener.PATHS, value="/")
public class JcrResourceBundleProvider implements ResourceBundleProvider, ResourceChangeListener, ExternalResourceChangeListener {

    private static final boolean DEFAULT_PRELOAD_BUNDLES = false;

    private static final int DEFAULT_INVALIDATION_DELAY = 5000;

    private static final String SLING_I18N_USER = "sling-i18n";

    @Property(value = "en")
    private static final String PROP_DEFAULT_LOCALE = "locale.default";

    @Property(boolValue = DEFAULT_PRELOAD_BUNDLES)
    private static final String PROP_PRELOAD_BUNDLES = "preload.bundles";

    @Property(longValue = DEFAULT_INVALIDATION_DELAY)
    private static final String PROP_INVALIDATION_DELAY = "invalidation.delay";

    @Reference
    private Scheduler scheduler;

    /** job names of scheduled jobs for reloading individual bundles */
    private final Collection<String> scheduledJobNames = Collections.synchronizedList(new ArrayList<String>()) ;

    /** default log */
    private final Logger log = LoggerFactory.getLogger(getClass());

    @Reference
    private ResourceResolverFactory resourceResolverFactory;

    /**
     * The default Locale as configured with the <i>locale.default</i>
     * configuration property. This defaults to <code>Locale.ENGLISH</code> if
     * the configuration property is not set.
     */
    private Locale defaultLocale = Locale.ENGLISH;

    /**
     * The resource resolver used to access the resource bundles. This object is
     * retrieved from the {@link #resourceResolverFactory} using the {@link #SLING_I18N_USER} service user session.
     */
    private ResourceResolver resourceResolver;

    /**
     * Map of cached resource bundles indexed by a key combined of the base name
     * and <code>Locale</code> used to load and identify the <code>ResourceBundle</code>.
     */
    private final ConcurrentHashMap<Key, JcrResourceBundle> resourceBundleCache = new ConcurrentHashMap<Key, JcrResourceBundle>();

    private final ConcurrentHashMap<Key, Semaphore> loadingGuards = new ConcurrentHashMap<Key, Semaphore>();

    /**
     * paths from which JCR resource bundles have been loaded
     */
    private final Set<String> languageRootPaths = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());

    /**
     * Return root resource bundle as created on-demand by
     * {@link #getRootResourceBundle()}.
     */
    private ResourceBundle rootResourceBundle;

    private BundleContext bundleContext;

    /**
     * Each ResourceBundle is registered as a service. Each registration is stored in this map with the locale & base name used as a key.
     */
    private final Map<Key, ServiceRegistration<ResourceBundle>> bundleServiceRegistrations = new HashMap<Key, ServiceRegistration<ResourceBundle>>();

    private boolean preloadBundles;

    private long invalidationDelay;

    // ---------- ResourceBundleProvider ---------------------------------------

    /**
     * Returns the configured default <code>Locale</code> which is used as a
     * fallback for {@link #getResourceBundle(Locale)} and also as the basis for
     * any messages requested from resource bundles.
     */
    @Override
    public Locale getDefaultLocale() {
        return defaultLocale;
    }

    /**
     * Returns the <code>ResourceBundle</code> for the given
     * <code>locale</code>.
     *
     * @param locale The <code>Locale</code> for which to return the resource
     *            bundle. If this is <code>null</code> the configured
     *            {@link #getDefaultLocale() default locale} is assumed.
     * @return The <code>ResourceBundle</code> for the given locale.
     * @throws MissingResourceException If the <code>ResourceResolver</code>
     *             is not available to access the resources.
     */
    @Override
    public ResourceBundle getResourceBundle(Locale locale) {
        return getResourceBundle(null, locale);
    }

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

        return getResourceBundleInternal(baseName, locale);
    }

    // ---------- EventHandler ------------------------------------------------

    @Override
    public void onChange(List<ResourceChange> changes) {
        boolean refreshed = false;
        for(final ResourceChange change : changes) {
            log.trace("handleEvent: Detecting event {} for path '{}'", change.getType(), change.getPath());

            // if this change was on languageRootPath level this might change basename and locale as well, therefore
            // invalidate everything
            if (languageRootPaths.contains(change.getPath())) {
                log.debug(
                        "handleEvent: Detected change of cached language root '{}', removing all cached ResourceBundles",
                        change.getPath());
                scheduleReloadBundles(true);
            } else {
                // if it is only a change below a root path, only messages of one resource bundle can be affected!
                for (final String root : languageRootPaths) {
                    if (change.getPath().startsWith(root)) {
                        // figure out which JcrResourceBundle from the cached ones is affected
                        for (JcrResourceBundle bundle : resourceBundleCache.values()) {
                            if (bundle.getLanguageRootPaths().contains(root)) {
                                // reload it
                                log.debug("handleEvent: Resource changes below '{}', reloading ResourceBundle '{}'",
                                        root, bundle);
                                scheduleReloadBundle(bundle);
                                return;
                            }
                        }
                        log.debug("handleEvent: No cached resource bundle found with root '{}'", root);
                        break;
                    }
                }
                // may be a completely new dictionary
                if (!refreshed) {
                    // refresh at most once per onChange()
                    resourceResolver.refresh();
                    refreshed = true;
                }
                if (isDictionaryResource(change)) {
                    scheduleReloadBundles(true);
                }
            }
        }
    }

    private boolean isDictionaryResource(final ResourceChange change) {
        // language node changes happen quite frequently (https://issues.apache.org/jira/browse/SLING-2881)
        // therefore only consider changes either for sling:MessageEntry's
        // or for JSON dictionaries
        // get valuemap
        final Resource resource = resourceResolver.getResource(change.getPath());
        if (resource == null) {
            log.trace("Could not get resource for '{}' for event {}", change.getPath(), change.getType());
            return false;
        }
        if ( resource.getResourceType() == null ) {
            return false;
        }
        if (resource.isResourceType(JcrResourceBundle.RT_MESSAGE_ENTRY)) {
            log.debug("Found new dictionary entry: New {} resource in '{}' detected", JcrResourceBundle.RT_MESSAGE_ENTRY, change.getPath());
            return true;
        }
        final ValueMap valueMap = resource.getValueMap();
        // FIXME: derivatives from mix:Message are not detected
        if (hasMixin(valueMap, JcrResourceBundle.MIXIN_MESSAGE)) {
            log.debug("Found new dictionary entry: New {} resource in '{}' detected", JcrResourceBundle.MIXIN_MESSAGE, change.getPath());
            return true;
        }
        if (change.getPath().endsWith(".json")) {
            // check for mixin
            if (hasMixin(valueMap, JcrResourceBundle.MIXIN_LANGUAGE)) {
                log.debug("Found new dictionary: New {} resource in '{}' detected", JcrResourceBundle.MIXIN_LANGUAGE, change.getPath());
                return true;
            }
        }
        return false;
    }

    private boolean hasMixin(ValueMap valueMap, String mixin) {
        final String[] mixins = valueMap.get(JcrResourceBundle.PROP_MIXINS, String[].class);
        if ( mixins != null ) {
            for(final String m : mixins) {
                if (mixin.equals(m) ) {
                    return true;
                }
            }
        }
        return false;
    }

    private void scheduleReloadBundles(boolean withDelay) {
        // cancel all reload individual bundle jobs!
        synchronized(scheduledJobNames) {
            for (String scheduledJobName : scheduledJobNames) {
                scheduler.unschedule(scheduledJobName);
            }
        }
        scheduledJobNames.clear();
        // defer this job
        final ScheduleOptions options;
        if (withDelay) {
            options = scheduler.AT(new Date(System.currentTimeMillis() + invalidationDelay));
        } else {
            options = scheduler.NOW();
        }
        options.name("JcrResourceBundleProvider: reload all resource bundles");
        scheduler.schedule(new Runnable() {
            @Override
            public void run() {
                log.info("Reloading all resource bundles");
                clearCache();
                preloadBundles();
            }
        }, options);
    }

    private void scheduleReloadBundle(JcrResourceBundle bundle) {
        String baseName = bundle.getBaseName();
        Locale locale = bundle.getLocale();
        final Key key = new Key(baseName, locale);

        // defer this job
        ScheduleOptions options = scheduler.AT(new Date(System.currentTimeMillis() + invalidationDelay));
        final String jobName = "JcrResourceBundleProvider: reload bundle with key " + key.toString();
        scheduledJobNames.add(jobName);
        options.name(jobName);
        scheduler.schedule(new Runnable() {
            @Override
            public void run() {
                reloadBundle(key);
                scheduledJobNames.remove(jobName);
            }
        }, options);
    }

    void reloadBundle(final Key key) {
        // remove bundle from cache
        resourceBundleCache.remove(key);
        log.info("Reloading resource bundle for {}", key);
        // unregister bundle
        ServiceRegistration<ResourceBundle> serviceRegistration = null;
        synchronized (this) {
            serviceRegistration = bundleServiceRegistrations.remove(key);
        }
        if (serviceRegistration != null) {
            serviceRegistration.unregister();
        } else {
            log.warn("Could not find resource bundle service for {}", key);
        }

        Collection<JcrResourceBundle> dependentBundles = new ArrayList<JcrResourceBundle>();
        // this bundle might be a parent of a cached bundle -> invalidate those dependent bundles as well
        for (JcrResourceBundle bundle : resourceBundleCache.values()) {
            if (bundle.getParent() instanceof JcrResourceBundle) {
                JcrResourceBundle parentBundle = (JcrResourceBundle) bundle.getParent();
                Key parentKey = new Key(parentBundle.getBaseName(), parentBundle.getLocale());
                if (parentKey.equals(key)) {
                    log.debug("Also invalidate dependent bundle {} which has bundle {} as parent", bundle, parentBundle);
                    dependentBundles.add(bundle);
                }
            }
        }
        for (JcrResourceBundle dependentBundle : dependentBundles) {
            reloadBundle(new Key(dependentBundle.getBaseName(), dependentBundle.getLocale()));
        }

        if (preloadBundles) {
            // reload the bundle from the repository (will also fill cache and register as a service)
            getResourceBundle(key.baseName, key.locale);
        }
    }

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

    /**
     * Activates and configures this component with the repository access
     * details and the default locale to use
     * @throws LoginException
     */
    protected void activate(BundleContext context, Map<String, Object> props) throws LoginException {
        String localeString = PropertiesUtil.toString(props.get(PROP_DEFAULT_LOCALE),
            null);
        this.defaultLocale = toLocale(localeString);
        this.preloadBundles = PropertiesUtil.toBoolean(props.get(PROP_PRELOAD_BUNDLES), DEFAULT_PRELOAD_BUNDLES);

        this.bundleContext = context;
        invalidationDelay = PropertiesUtil.toLong(props.get(PROP_INVALIDATION_DELAY), DEFAULT_INVALIDATION_DELAY);
        if (this.resourceResolverFactory != null) { // this is only null during test execution!
            Map<String, Object> authInfo = Collections.<String, Object>singletonMap(
                    ResourceResolverFactory.SUBSERVICE, SLING_I18N_USER);
            resourceResolver = resourceResolverFactory.getServiceResourceResolver(authInfo);
            scheduleReloadBundles(false);
        }

    }

    protected void deactivate() {
        clearCache();
        resourceResolver.close();
    }

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

    /**
     * Internal implementation of the {@link #getResourceBundle(Locale)} method
     * employing the cache of resource bundles. Creates the bundle if not
     * already cached.
     *
     * @throws MissingResourceException If the resource bundles needs to be
     *             created and the <code>ResourceResolver</code> is not
     *             available to access the resources.
     */
    private ResourceBundle getResourceBundleInternal(final String baseName, final Locale locale) {
        final Key key = new Key(baseName, locale);
        JcrResourceBundle resourceBundle = resourceBundleCache.get(key);
        if (resourceBundle != null) {
            log.debug("getResourceBundleInternal({}): got cache hit on first try", key);
        } else {
            if (loadingGuards.get(key) == null) {
                loadingGuards.putIfAbsent(key, new Semaphore(1));
            }
            final Semaphore loadingGuard = loadingGuards.get(key);
            try {
                loadingGuard.acquire();
                resourceBundle = resourceBundleCache.get(key);
                if (resourceBundle != null) {
                    log.debug("getResourceBundleInternal({}): got cache hit on second try", key);
                } else {
                    log.debug("getResourceBundleInternal({}): reading from Repository", key);
                    resourceBundle = createResourceBundle(key.baseName, key.locale);
                    resourceBundleCache.put(key, resourceBundle);
                    registerResourceBundle(key, resourceBundle);
                }
            } catch (InterruptedException e) {
                Thread.interrupted();
            } finally {
                loadingGuard.release();
            }
        }
        log.trace("getResourceBundleInternal({}) ==> {}", key, resourceBundle);
        return resourceBundle;
    }

    private void registerResourceBundle(Key key, JcrResourceBundle resourceBundle) {
        Dictionary<String, Object> serviceProps = new Hashtable<String, Object>();
        if (key.baseName != null) {
            serviceProps.put("baseName", key.baseName);
        }
        serviceProps.put("locale", key.locale.toString());
        ServiceRegistration<ResourceBundle> serviceReg = bundleContext.registerService(ResourceBundle.class,
                resourceBundle, serviceProps);
        synchronized (this) {
            bundleServiceRegistrations.put(key, serviceReg);
        }

        // register language root paths
        final Set<String> languageRoots = resourceBundle.getLanguageRootPaths();
        this.languageRootPaths.addAll(languageRoots);

        log.debug("registerResourceBundle({}, ...): added service registration and language roots {}", key, languageRoots);
        log.info("Currently loaded dictionaries across all locales: {}", languageRootPaths);
    }

    /**
     * Creates the resource bundle for the give locale.
     *
     * @throws MissingResourceException If the <code>ResourceResolver</code>
     *             is not available to access the resources.
     */
    private JcrResourceBundle createResourceBundle(String baseName, Locale locale) {
        final JcrResourceBundle bundle = new JcrResourceBundle(locale, baseName, resourceResolver);

        // set parent resource bundle
        Locale parentLocale = getParentLocale(locale);
        if (parentLocale != null) {
            bundle.setParent(getResourceBundleInternal(baseName, parentLocale));
        } else {
            bundle.setParent(getRootResourceBundle());
        }

        return bundle;
    }

    /**
     * Returns the parent locale of the given locale. The parent locale is the
     * locale of a locale is defined as follows:
     * <ol>
     * <li>If the locale has an variant, the parent locale is the locale with
     * the same language and country without the variant.</li>
     * <li>If the locale has no variant but a country, the parent locale is the
     * locale with the same language but neither country nor variant.</li>
     * <li>If the locale has no country and not variant and whose language is
     * different from the language of the the configured default locale, the
     * parent locale is the configured default locale.</li>
     * <li>Otherwise there is no parent locale and <code>null</code> is
     * returned.</li>
     * </ol>
     */
    private Locale getParentLocale(Locale locale) {
        if (locale.getVariant().length() != 0) {
            return new Locale(locale.getLanguage(), locale.getCountry());
        } else if (locale.getCountry().length() != 0) {
            return new Locale(locale.getLanguage());
        } else if (!locale.getLanguage().equals(defaultLocale.getLanguage())) {
            return defaultLocale;
        }

        // no more parents
        return null;
    }

    /**
     * Returns a ResourceBundle which is used as the root resource bundle, that
     * is the ultimate parent:
     * <ul>
     * <li><code>getLocale()</code> returns Locale("", "", "")</li>
     * <li><code>handleGetObject(String key)</code> returns the <code>key</code></li>
     * <li><code>getKeys()</code> returns an empty enumeration.
     * </ul>
     *
     * @return The root resource bundle
     */
    private ResourceBundle getRootResourceBundle() {
        if (rootResourceBundle == null) {
            rootResourceBundle = new RootResourceBundle();
        }
        return rootResourceBundle;
    }

    private void clearCache() {
        resourceBundleCache.clear();
        languageRootPaths.clear();

        synchronized (this) {
            for (ServiceRegistration<ResourceBundle> serviceReg : bundleServiceRegistrations.values()) {
                serviceReg.unregister();
            }
            bundleServiceRegistrations.clear();
        }
    }

    private void preloadBundles() {
        if (preloadBundles) {
            resourceResolver.refresh();
            Iterator<Map<String, Object>> bundles = resourceResolver.queryResources(
                    JcrResourceBundle.QUERY_LANGUAGE_ROOTS, "xpath");
            Set<Key> usedKeys = new HashSet<Key>();
            while (bundles.hasNext()) {
                Map<String,Object> bundle = bundles.next();
                if (bundle.containsKey(PROP_LANGUAGE)) {
                    Locale locale = toLocale(bundle.get(PROP_LANGUAGE).toString());
                    String baseName = null;
                    if (bundle.containsKey(PROP_BASENAME)) {
                        baseName = bundle.get(PROP_BASENAME).toString();
                    }
                    Key key = new Key(baseName, locale);
                    if (usedKeys.add(key)) {
                        getResourceBundle(baseName, locale);
                    }
                }
            }
        }
    }

    /**
     * Converts the given <code>localeString</code> to a valid
     * <code>java.util.Locale</code>. It must either be in the format specified by
     * {@link Locale#toString()} or in <a href="https://tools.ietf.org/html/bcp47">BCP 47 format</a>
     * If the locale string is <code>null</code> or empty, the platform default locale is assumed. If
     * the localeString matches any locale available per default on the
     * platform, that platform locale is returned. Otherwise the localeString is
     * parsed and the language and country parts are compared against the
     * languages and countries provided by the platform. Any unsupported
     * language or country is replaced by the platform default language and
     * country.
     * @param localeString the locale as string
     * @return the {@link Locale} being generated from the {@code localeString}
     */
    static Locale toLocale(String localeString) {
        if (localeString == null || localeString.length() == 0) {
            return Locale.getDefault();
        }
        // support BCP 47 compliant strings as well (using a different separator "-" instead of "_")
        localeString = localeString.replaceAll("-", "_");

        // check language and country
        final String[] parts = localeString.split("_");
        if (parts.length == 0) {
            return Locale.getDefault();
        }

        // at least language is available
        String lang = parts[0];
        boolean isValidLanguageCode = false;
        String[] langs = Locale.getISOLanguages();
        for (int i = 0; i < langs.length; i++) {
            if (langs[i].equalsIgnoreCase(lang)) {
                isValidLanguageCode = true;
                break;
            }
        }
        if (!isValidLanguageCode) {
            lang = Locale.getDefault().getLanguage();
        }

        // only language
        if (parts.length == 1) {
            return new Locale(lang);
        }

        // country is also available
        String country = parts[1];
        boolean isValidCountryCode = false;
        String[] countries = Locale.getISOCountries();
        for (int i = 0; i < countries.length; i++) {
            if (countries[i].equalsIgnoreCase(country)) {
                isValidCountryCode = true; // signal ok
                break;
            }
        }
        if (!isValidCountryCode) {
            country = Locale.getDefault().getCountry();
        }

        // language and country
        if (parts.length == 2) {
            return new Locale(lang, country);
        }

        // language, country and variant
        return new Locale(lang, country, parts[2]);
    }

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

    /**
     * The <code>Key</code> class encapsulates the base name and Locale in a
     * single object that can be used as the key in a <code>HashMap</code>.
     */
    protected static final class Key {

        final String baseName;

        final Locale locale;

        // precomputed hash code, because this will always be used due to
        // this instance being used as a key in a HashMap.
        private final int hashCode;

        Key(final String baseName, final Locale locale) {

            int hc = 0;
            if (baseName != null) {
                hc += 17 * baseName.hashCode();
            }
            if (locale != null) {
                hc += 13 * locale.hashCode();
            }

            this.baseName = baseName;
            this.locale = locale;
            this.hashCode = hc;
        }

        @Override
        public int hashCode() {
            return hashCode;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == this) {
                return true;
            } else if (obj instanceof Key) {
                Key other = (Key) obj;
                return equals(this.baseName, other.baseName)
                    && equals(this.locale, other.locale);
            }

            return false;
        }

        private static boolean equals(Object o1, Object o2) {
            if (o1 == null) {
                if (o2 != null) {
                    return false;
                }
            } else if (!o1.equals(o2)) {
                return false;
            }
            return true;
        }

        @Override
        public String toString() {
            return "Key(" + baseName + ", " + locale + ")";
        }
    }
}
