/*
 * 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.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;

import org.apache.jackrabbit.commons.json.JsonHandler;
import org.apache.jackrabbit.commons.json.JsonParser;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceMetadata;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JcrResourceBundle extends ResourceBundle {

    private static final Logger log = LoggerFactory.getLogger(JcrResourceBundle.class);

    /** default primary type (=resource type) for message entry dictionaries */
    static final String RT_MESSAGE_ENTRY = "sling:MessageEntry";

    static final String MIXIN_MESSAGE = "sling:Message";

    static final String MIXIN_LANGUAGE = "mix:language";

    static final String PROP_KEY = "sling:key";

    static final String PROP_VALUE = "sling:message";

    static final String PROP_BASENAME = "sling:basename";

    static final String PROP_LANGUAGE = "jcr:language";

    static final String PROP_MIXINS = "jcr:mixinTypes";

    static final String QUERY_LANGUAGE_ROOTS = "//element(*,mix:language)[@jcr:language]";

    private final Map<String, Object> resources;

    private final Locale locale;

    private final String baseName;

    private final Set<String> languageRoots = new HashSet<>();

    JcrResourceBundle(final Locale locale, final String baseName,
            final ResourceResolver resourceResolver) {
        this(locale, baseName, resourceResolver, Collections.<LocatorPaths>emptyList());
    }

    JcrResourceBundle(final Locale locale, final String baseName,
            final ResourceResolver resourceResolver, List<LocatorPaths> locatorPaths) {
        this.locale = locale;
        this.baseName = baseName;

        log.info("Finding all dictionaries for '{}' (basename: {}) ...", locale, baseName == null ? "<none>" : baseName);

        final long start = System.currentTimeMillis();
        final Set<String> roots = loadPotentialLanguageRoots(resourceResolver, locale, baseName, locatorPaths);
        this.resources = loadFully(resourceResolver, roots, this.languageRoots);

        if (log.isInfoEnabled()) {
            final long end = System.currentTimeMillis();
            log.info(
                "Finished loading {} entries for '{}' (basename: {}) in {}ms",
                new Object[] { resources.size(), locale, baseName == null ? "<none>" : baseName, (end - start)}
            );
        }
    }

    protected Set<String> getLanguageRootPaths() {
        return languageRoots;
    }

    @Override
    protected void setParent(ResourceBundle parent) {
        super.setParent(parent);
    }

    public ResourceBundle getParent() {
        return parent;
    }

    @Override
    public Locale getLocale() {
        return locale;
    }

    public String getBaseName() {
        return baseName;
    }

    /**
     * Returns a Set of all resource keys provided by this resource bundle only.
     * <p>
     * This method is a new Java 1.6 method to implement the
     * ResourceBundle.keySet() method.
     *
     * @return The keys of the resources provided by this resource bundle
     */
    @Override
    protected Set<String> handleKeySet() {
        return resources.keySet();
    }

    @Override
    public Enumeration<String> getKeys() {
        Enumeration<String> parentKeys = (parent != null)
                ? parent.getKeys()
                : null;
        return new ResourceBundleEnumeration(resources.keySet(), parentKeys);
    }

    @Override
    protected Object handleGetObject(String key) {
        if (log.isDebugEnabled()) {
            log.debug("Requesting key '{}' from resource bundle (baseName '{}', locale '{}')", new Object[] {key, baseName, locale});
        }
        return resources.get(key);
    }

    /**
     * Fully loads the resource bundle from the storage.
     * <p>
     * This method adds entries to the {@code languageRoots} set of strings.
     * Therefore this method must not be called concurrently or the set
     * must either be thread safe.
     *
     * @param resolver The storage access (must not be {@code null})
     * @param roots The set of (potential) dictionary subtrees. This must
     *      not be {@code null}. If empty, no resources will actually be
     *      loaded.
     * @param languageRoots The set of actually dictionary subtrees. While
     *      processing the resources, all subtrees listed in the {@code roots}
     *      set is added to this set if it actually contains resources. This
     *      must not be {@code null}.
     * @return
     *
     * @throws NullPointerException if either of the parameters is {@code null}.
     */
    private Map<String, Object> loadFully(final ResourceResolver resolver, Set<String> roots, Set<String> languageRoots) {

        final String[] searchPath = resolver.getSearchPath();

        // for each search path entry, have a list of maps (dictionaries)
        // plus other = "outside the search path" at the end

        //   [0] /apps2  -> [dict1, dict2, dict3 ...]
        //   [1] /apps   -> [dict4, dict5, ...]
        //   [2] /libs   -> [dict6, ...]
        //   [3] (other) -> [dict7, dict8 ...]

        List<List<Map<String, Object>>> dictionariesBySearchPath = new ArrayList<>(searchPath.length + 1);
        for (int i = 0; i < searchPath.length + 1; i++) {
            dictionariesBySearchPath.add(new ArrayList<Map<String, Object>>());
        }

        for (final String root: roots) {

            Resource dictionaryResource = resolver.getResource(root);
            if (dictionaryResource == null) {
                log.warn("Dictionary root found by search not accessible: {}", root);
                continue;
            }

            // linked hash map to keep order (not functionally important, but helpful for dictionary debugging)
            Map<String, Object> dictionary = new LinkedHashMap<>();

            // find where in the search path this dict belongs
            // otherwise put it in the outside-the-search-path bucket (last list)
            List<Map<String, Object>> targetList = dictionariesBySearchPath.get(searchPath.length);
            for (int i = 0; i < searchPath.length; i++) {
                if (root.startsWith(searchPath[i])) {
                    targetList = dictionariesBySearchPath.get(i);
                    break;
                }
            }
            targetList.add(dictionary);

            // check type of dictionary
            if (dictionaryResource.getName().endsWith(".json")) {
                loadJsonDictionary(dictionaryResource, dictionary);
            } else {
                loadSlingMessageDictionary(dictionaryResource, dictionary);
            }

            languageRoots.add(root);
        }

        // linked hash map to keep order (not functionally important, but helpful for dictionary debugging)
        final Map<String, Object> result = new LinkedHashMap<>();

        // first, add everything that's not under a search path (e.g. /content)
        // below, same strings inside a search path dictionary would overlay them since
        // they are added later to result = overwrite
        for (Map<String, Object> dict : dictionariesBySearchPath.get(searchPath.length)) {
            result.putAll(dict);
        }

        // then, in order of the search path, add all the individual dictionaries into
        // a single result, so that e.g. strings in /apps overlay the ones in /libs
        for (int i = searchPath.length - 1; i >= 0; i--) {

            for (Map<String, Object> dict : dictionariesBySearchPath.get(i)) {
                result.putAll(dict);
            }
        }

        return result;
    }

    private void loadJsonDictionary(Resource resource, final Map<String, Object> targetDictionary) {
        log.info("Loading json dictionary: {}", resource.getPath());

        // use streaming parser (we don't need the dict in memory twice)
        JsonParser parser = new JsonParser(new JsonHandler() {

            private String key;

            @Override
            public void key(String key) throws IOException {
                this.key = key;
            }

            @Override
            public void value(String value) throws IOException {
                targetDictionary.put(key, value);
            }

            @Override
            public void object() throws IOException {}
            @Override
            public void endObject() throws IOException {}
            @Override
            public void array() throws IOException {}
            @Override
            public void endArray() throws IOException {}
            @Override
            public void value(boolean value) throws IOException {}
            @Override
            public void value(long value) throws IOException {}
            @Override
            public void value(double value) throws IOException {}
        });

        final InputStream stream = resource.adaptTo(InputStream.class);
        if (stream != null) {
            String encoding = "utf-8";
            final ResourceMetadata metadata = resource.getResourceMetadata();
            if (metadata.getCharacterEncoding() != null) {
                encoding = metadata.getCharacterEncoding();
            }

            try {

                parser.parse(stream, encoding);

            } catch (IOException e) {
                log.warn("Could not parse i18n json dictionary {}: {}", resource.getPath(), e.getMessage());
            } finally {
                try {
                    stream.close();
                } catch (IOException ignore) {
                }
            }
        } else {
            log.warn("Not a json file: {}", resource.getPath());
        }
    }

    /**
     * Depth-first traversal of a resource tree
     */
    private void scanForSlingMessages(final Resource rsrc, final Map<String, Object> targetDictionary) {
        final ValueMap vm = rsrc.adaptTo(ValueMap.class);
        if ( vm != null ) {
            final String value = vm.get(PROP_VALUE, String.class);
            if ( value != null ) {
                final String key = vm.get(PROP_KEY, rsrc.getName());
                targetDictionary.put(key, value);
            }
        }

        for(final Resource c : rsrc.getChildren()) {
            scanForSlingMessages(c, targetDictionary);
        }
    }

    private void loadSlingMessageDictionary(final Resource dictionaryResource, final Map<String, Object> targetDictionary) {
        log.info("Loading sling:Message dictionary: {}", dictionaryResource.getPath());

        this.scanForSlingMessages(dictionaryResource, targetDictionary);
    }

    private Set<String> loadPotentialLanguageRoots(ResourceResolver resourceResolver, Locale locale, final String baseName, Collection<LocatorPaths> locatorPaths) {
        final Set<String> paths = new LinkedHashSet<>();

        PotentialLanguageRootCheck check = new PotentialLanguageRootCheck(baseName, locale);

        // first consider resource bundles in the JCR repository
        final Iterator<Resource> bundles = resourceResolver.findResources(QUERY_LANGUAGE_ROOTS, "xpath");
        while (bundles.hasNext()) {
            Resource bundle = bundles.next();
            if (check.isResourceBundle(bundle)) {
                paths.add(bundle.getPath());
            }
        }

        if (locatorPaths != null && !locatorPaths.isEmpty()) {
            // next traverse the ancestors of all of the locator paths
            LocatorPathsVisitor visitor = new LocatorPathsVisitor(check, paths);
            for (LocatorPaths locator : locatorPaths) {
                Resource parentResource = resourceResolver.getResource(locator.getPath());
                if (parentResource != null) {
                    visitor.accept(parentResource, locator.getTraverseDepth());
                }
            }
        }

        return Collections.unmodifiableSet(paths);
    }

    @Override
    public String toString() {
        return "JcrResourceBundle [locale=" + locale + ", baseName=" + baseName + ", languageRoots=" + languageRoots
                + ", parent=" + parent + "]";
    }
}
