/*
 * Copyright 2017-present Open Networking Laboratory
 *
 * Licensed 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.onosproject.ui.impl.lion;

import com.google.common.collect.ImmutableList;
import org.onosproject.ui.lion.LionBundle;
import org.onosproject.ui.lion.LionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Set;

/**
 * Gathers and stitches together a localization bundle according to a
 * "lion" configuration file.
 */
public class BundleStitcher {

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

    private static final String CONFIG_DIR = "_config";
    private static final String SUFFIX = ".lioncfg";
    private static final String SLASH = "/";
    private static final String DOT = ".";


    private final String base;

    /**
     * Creates a bundle stitcher, configured with the specified base resource
     * path.
     *
     * @param base the base resource path
     */
    public BundleStitcher(String base) {
        this.base = base;
    }

    @Override
    public String toString() {
        return "BundleStitcher{base=\"" + base + "\"}";
    }

    /**
     * Stitches together a LionBundle, based on the bundle configuration data
     * for the given bundle ID.
     *
     * @param id the bundle ID
     * @return a corresponding lion bundle
     * @throws IllegalArgumentException if the bundle config cannot be loaded
     */
    public LionBundle stitch(String id) {
        String source = base + SLASH + CONFIG_DIR + SLASH + id + SUFFIX;
        LionConfig cfg = new LionConfig().load(source);
        LionBundle.Builder builder = new LionBundle.Builder(id);

        for (LionConfig.CmdFrom from : cfg.entries()) {
            addItemsToBuilder(builder, from);
        }

        return builder.build();
    }

    private void addItemsToBuilder(LionBundle.Builder builder,
                                   LionConfig.CmdFrom from) {
        String resBundleName = base + SLASH + from.res();
        String resFqbn = convertToFqbn(resBundleName);
        ResourceBundle bundle = LionUtils.getBundledResource(resFqbn);

        if (from.starred()) {
            addAllItems(builder, bundle);
        } else {
            addItems(builder, bundle, from.keys());
        }
    }

    // to fully-qualified-bundle-name
    private String convertToFqbn(String path) {
        if (!path.startsWith(SLASH)) {
            throw new IllegalArgumentException("path should start with '/'");
        }
        return path.substring(1).replaceAll(SLASH, DOT);
    }

    private void addAllItems(LionBundle.Builder builder, ResourceBundle bundle) {
        addItems(builder, bundle, bundle.keySet());
    }

    private void addItems(LionBundle.Builder builder, ResourceBundle bundle,
                          Set<String> keys) {
        keys.forEach(k -> builder.addItem(k, bundle.getString(k)));
    }

    /**
     * Generates an immutable list of localization bundles, using the specified
     * resource tree (base) and localization configuration file names (tags).
     * <p>
     * As an example, you might invoke:
     * <pre>
     * private static final String LION_BASE = "/org/onosproject/ui/lion";
     *
     * private static final String[] LION_TAGS = {
     *     "core.view.App",
     *     "core.view.Settings",
     *     "core.view.Cluster",
     *     "core.view.Processor",
     *     "core.view.Partition",
     * };
     *
     * List&lt;LionBundle&gt; bundles =
     *      LionUtils.generateBundles(LION_BASE, LION_TAGS);
     * </pre>
     * It is expected that in the "LION_BASE" directory there is a subdirectory
     * named "_config" which contains the configuration files listed in the
     * "LION_TAGS" array, each with a ".lioncfg" suffix...
     * <pre>
     * /org/onosproject/ui/lion/
     *   |
     *   +-- _config
     *         |
     *         +-- core.view.App.lioncfg
     *         +-- core.view.Settings.lioncfg
     *         :
     * </pre>
     * These files collate a localization bundle for their particular view
     * by referencing resource bundles and their keys.
     *
     * @param base the base resource directory path
     * @param tags the list of bundles to generate
     * @return a list of generated localization bundles
     */
    public static List<LionBundle> generateBundles(String base,
                                                   String... tags) {
        List<LionBundle> result = new ArrayList<>(tags.length);
        BundleStitcher stitcher = new BundleStitcher(base);
        for (String tag : tags) {
            try {
                LionBundle b = stitcher.stitch(tag);
                result.add(b);

            } catch (IllegalArgumentException e) {
                log.warn("Unable to generate bundle: {} / {}", base, tag);
            }
        }
        return ImmutableList.copyOf(result);
    }
}
