/*
 *
 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * - Neither the name of Oracle nor the names of its contributors may be used to
 * endorse or promote products derived from this software without specific prior
 * written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.IOException;
import java.util.Properties;
import java.util.ResourceBundle;

/**
 * <code>TextAndMnemonicUtils</code> allows to extract text and mnemonic values
 * from the unified text & mnemonic strings. For example:
 *   LafMenu.laf.labelAndMnemonic=&Look && Feel
 * The extracted text is "Look & Feel" and the extracted mnemonic mnemonic is "L".
 *
 * There are several patterns for the text and mnemonic suffixes which are used
 * in the resource file. The patterns format is:
 * (resource key -> unified text & mnemonic resource key).
 *
 * Keys that have label suffixes:
 * (xxx_label -> xxx.labelAndMnemonic)
 *
 * Keys that have mnemonic suffixes:
 * (xxx_mnemonic -> xxx.labelAndMnemonic)
 *
 * Keys that do not have definite suffixes:
 * (xxx -> xxx.labelAndMnemonic)
 *
 * @author Alexander Scherbatiy
 */
public class TextAndMnemonicUtils {

    // Label suffix for the text & mnemonic resource
    private static final String LABEL_SUFFIX = ".labelAndMnemonic";

    // Resource bundle for internationalized and accessible text
    private static ResourceBundle bundle = null;

    // Resource properties for the mnemonic key defenition
    private static Properties properties = null;

    static {
        bundle = ResourceBundle.getBundle("resources.swingset");
        properties = new Properties();
        try {
            properties.load(TextAndMnemonicUtils.class.getResourceAsStream("resources/swingset.properties"));
        } catch (IOException ex) {
            System.out.println("java.io.IOException: Couldn't load properties from: resources/swingset.properties");
        }
    }

    /**
     * Returns accessible and internationalized strings or mnemonics from the
     * resource bundle. The key is converted to the text & mnemonic key.
     *
     * The following patterns are checked:
     * Keys that have label suffixes:
     * (xxx_label -> xxx.labelAndMnemonic)
     *
     * Keys that have mnemonic suffixes:
     * (xxx_mnemonic -> xxx.labelAndMnemonic)
     *
     * Keys that do not have definite suffixes:
     * (xxx -> xxx.labelAndMnemonic)
     *
     * Properties class is used to check if a key created for mnemonic exists.
     */
    public static String getTextAndMnemonicString(String key) {

        if (key.endsWith("_label")) {
            String compositeKey = composeKey(key, 6, LABEL_SUFFIX);
            String textAndMnemonic = bundle.getString(compositeKey);
            return getTextFromTextAndMnemonic(textAndMnemonic);
        }

        if (key.endsWith("_mnemonic")) {

            String compositeKey = composeKey(key, 9, LABEL_SUFFIX);
            Object value = properties.getProperty(compositeKey);

            if (value != null) {
                String textAndMnemonic = bundle.getString(compositeKey);
                return getMnemonicFromTextAndMnemonic(textAndMnemonic);
            }

        }

        String compositeKey = composeKey(key, 0, LABEL_SUFFIX);
        Object value = properties.getProperty(compositeKey);

        if (value != null) {
            String textAndMnemonic = bundle.getString(compositeKey);
            return getTextFromTextAndMnemonic(textAndMnemonic);
        }

        String textAndMnemonic = bundle.getString(key);
        return getTextFromTextAndMnemonic(textAndMnemonic);
    }

    /**
     * Convert the text & mnemonic string to text string
     *
     * The '&' symbol is treated as the mnemonic pointer
     * The double "&&" symbols are treated as the single '&'
     *
     * For example the string "&Look && Feel" is converted to "Look & Feel"
     */
    public static String getTextFromTextAndMnemonic(String text) {

        StringBuilder sb = new StringBuilder();

        int prevIndex = 0;
        int nextIndex = text.indexOf('&');
        int len = text.length();

        while (nextIndex != -1) {

            String s = text.substring(prevIndex, nextIndex);
            sb.append(s);

            nextIndex++;

            if (nextIndex != len && text.charAt(nextIndex) == '&') {
                sb.append('&');
                nextIndex++;
            }

            prevIndex = nextIndex;
            nextIndex = text.indexOf('&', nextIndex + 1);
        }

        sb.append(text.substring(prevIndex, text.length()));
        return sb.toString();
    }

    /**
     * Convert the text & mnemonic string to mnemonic
     *
     * The '&' symbol is treated the mnemonic pointer
     * The double "&&" symbols are treated as the single '&'
     *
     * For example the string "&Look && Feel" is converted to "L"
     */
    public static String getMnemonicFromTextAndMnemonic(String text) {
        int len = text.length();
        int index = text.indexOf('&');

        while (0 <= index && index < text.length() - 1) {
            index++;
            if (text.charAt(index) == '&') {
                index = text.indexOf('&', index + 1);
            } else {
                char c = text.charAt(index);
                return String.valueOf(Character.toUpperCase(c));
            }
        }

        return null;
    }

    /**
     * Removes the last n characters and adds the suffix
     */
    private static String composeKey(String key, int reduce, String sufix) {
        return key.substring(0, key.length() - reduce) + sufix;
    }
}
