/** Copyright © 2003 by Jean-Hugues de Raigniac <jhraigniac@workingfrog.org>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
 */

package org.workingfrog.i18n.util;

import java.util.HashSet;
import java.util.Locale;
import java.util.MissingResourceException;

/**
 * A tool class to help localization.
 *
 * @author Jean-Hugues de Raigniac
 *
 */
public class Translator {

    /** Enable lazy load of bundles. */
    private static HashSet loadedBundles = new HashSet();

    /** Will contain all checking logic. */
    private static Validator validator = new Validator();

    /** Locale used in default resource bundle. */
    private static Locale defaultLocale = new Locale("en", "");

    public static void init () {
        PropertiesLoader.init();
        LogLevel.setCurrent(PropertiesLoader.getLogLevel());
    }

    public static String getBundlesPath () {
        return PropertiesLoader.getBundlesPath();
    }

    public static void setBundlesPath (String path) {
        PropertiesLoader.setBundlesPath(path);
    }

    public static String getLogLevel () {
        return PropertiesLoader.getLogLevel();
    }

    public static void setLogLevel (String level) {
        PropertiesLoader.setLogLevel(level);
        LogLevel.setCurrent(level);
    }

    public static void setLogLevel (LogLevel level) {
        PropertiesLoader.setLogLevel(level);
        LogLevel.setCurrent(level);
    }

    public static void loadBundle (String binding, String resource) {
        boolean succeeded = true;

        try {
            loadedBundles.add(binding);
            Localizer.addResource(binding, resource);
        } catch (MissingResourceException e) {
            Translator.log(LogLevel.I18N,
                "Resource " + resource + " not found.");
            succeeded = false;
        }

        if (succeeded) {
            validator.storeBundle(binding);
        }
    }

    public static void loadBundle (String binding) {
        Translator.loadBundle(binding, getBundlesPath() + "." + binding);
    }

    public static void setDefaultLocale (Locale locale) {
        Translator.defaultLocale = locale;
    }

    public static void setLocale (Locale locale) {
        Localizer.switchCurrentLocale(locale);
        validator.clearLogs();
    }

    public static Locale getCurrentLocale () {
        return Locale.getDefault();
    }

    /**
     * Migration method : while older i18n process is still active in
     * application, returns legacy values for legacy keys.
     * 
     * @param i18nKey key to localize
     * @param legacyValue obtained from legacy i18n process, returned if
     * legacy key
     * @return localised value for i18nKey
     */
    public static String localize (String i18nKey, String legacyValue) {

        if (!isValidBundle(i18nKey)) {
            return legacyValue;
        }

        return localize(i18nKey);
    }

    public static String localize (String i18nKey) {

        lazyLoadBundle(validator.getBinding(i18nKey));

        if (!validator.check(i18nKey)) {
            Translator.log(validator.getReport());
        }

        return validator.getLocalizedValue();
    }

    private static void lazyLoadBundle (String binding) {
        if (!loadedBundles.contains(binding)) {
            Translator.loadBundle(binding);
        }
    }

    public static void checkKey (String i18nKey, Object source) {
//    public static void checkKey (String i18nKey) {
        if (!validator.checkName(i18nKey)) {
            Translator.log(validator.getReport());
        }
    }

    public static boolean isValidBundle (String i18nKey) {
        lazyLoadBundle(validator.getBinding(i18nKey));

        return validator.checkBundle(validator.getBinding(i18nKey));
    }

    public static String checkValue (String i18nKey, Object source) {
//        return Translator.localize(i18nKey, source);
        return Translator.localize(i18nKey);
    }

    public static boolean checkObject (Object object, Object source) {
        return validator.isLocaleListener(object, source);
    }

    public static void log (LogLevel level, String message) {
        if (LogLevel.isChecking(level)) {
            Translator.log(message);
        }
    }

    public static void log (String message) {
        System.out.println(message);
    }

    public static Locale[] getLocales () {
        return getLocales(getBundlesPath());
    }

    public static Locale[] getLocales (Object object) {
        Locale[] locales = Localizer.getLocales(object);
        Locale[] result = new Locale[locales.length + 1];
        result[0] = Translator.defaultLocale;
        for (int i = 0; i < locales.length; i++) {
            result[i + 1] = locales[i];
        }
        return result;
    }
}
