content: /*
   * Copyright (C) 2011 The Android Open Source Project
   *
   * 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 com.amnesica.kryptey.inputmethod.latin.utils;
  
  import android.content.Context;
  import android.content.res.Resources;
  
  import com.amnesica.kryptey.inputmethod.R;
  import com.amnesica.kryptey.inputmethod.latin.common.LocaleUtils;
  import com.amnesica.kryptey.inputmethod.latin.common.StringUtils;
  
  import java.util.HashMap;
  import java.util.Locale;
  
  /**
   * A helper class to deal with displaying locales.
   */
  public final class LocaleResourceUtils {
    // This reference class {@link R} must be located in the same package as LatinIME.java.
    private static final String RESOURCE_PACKAGE_NAME = "com.amnesica.kryptey";
  
    private static volatile boolean sInitialized = false;
    private static final Object sInitializeLock = new Object();
    private static Resources sResources;
    // Exceptional locale whose name should be displayed in Locale.ROOT.
    private static final HashMap<String, Integer> sExceptionalLocaleDisplayedInRootLocale =
        new HashMap<>();
    // Exceptional locale to locale name resource id map.
    private static final HashMap<String, Integer> sExceptionalLocaleToNameIdsMap = new HashMap<>();
    private static final String LOCALE_NAME_RESOURCE_PREFIX =
        "string/locale_name_";
    private static final String LOCALE_NAME_RESOURCE_IN_ROOT_LOCALE_PREFIX =
        "string/locale_name_in_root_locale_";
  
    private LocaleResourceUtils() {
      // Intentional empty constructor for utility class.
    }
  
    // Note that this initialization method can be called multiple times.
    public static void init(final Context context) {
      synchronized (sInitializeLock) {
        if (sInitialized == false) {
          initLocked(context);
          sInitialized = true;
        }
      }
    }
  
    private static void initLocked(final Context context) {
      final Resources res = context.getResources();
      sResources = res;
  
      final String[] exceptionalLocaleInRootLocale = res.getStringArray(
          R.array.locale_displayed_in_root_locale);
      for (int i = 0; i < exceptionalLocaleInRootLocale.length; i++) {
        final String localeString = exceptionalLocaleInRootLocale[i];
        final String resourceName = LOCALE_NAME_RESOURCE_IN_ROOT_LOCALE_PREFIX + localeString;
        final int resId = res.getIdentifier(resourceName, null, RESOURCE_PACKAGE_NAME);
        sExceptionalLocaleDisplayedInRootLocale.put(localeString, resId);
      }
  
      final String[] exceptionalLocales = res.getStringArray(R.array.locale_exception_keys);
      for (int i = 0; i < exceptionalLocales.length; i++) {
        final String localeString = exceptionalLocales[i];
        final String resourceName = LOCALE_NAME_RESOURCE_PREFIX + localeString;
        final int resId = res.getIdentifier(resourceName, null, RESOURCE_PACKAGE_NAME);
        sExceptionalLocaleToNameIdsMap.put(localeString, resId);
      }
    }
  
    private static Locale getDisplayLocale(final String localeString) {
      if (sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) {
        return Locale.ROOT;
      }
      return LocaleUtils.constructLocaleFromString(localeString);
    }
  
    /**
     * Get the full display name of the locale in the system's locale.
     * For example in an English system, en_US: "English (US)", fr_CA: "French (Canada)"
     *
     * @param localeString the locale to display.
     * @return the full display name of the locale.
     */
    public static String getLocaleDisplayNameInSystemLocale(
        final String localeString) {
      final Locale displayLocale = sResources.getConfiguration().locale;
      return getLocaleDisplayNameInternal(localeString, displayLocale);
    }
  
    /**
     * Get the full display name of the locale in its locale.
     * For example, en_US: "English (US)", fr_CA: "Français (Canada)"
     *
     * @param localeString the locale to display.
     * @return the full display name of the locale.
     */
    public static String getLocaleDisplayNameInLocale(final String localeString) {
      final Locale displayLocale = getDisplayLocale(localeString);
      return getLocaleDisplayNameInternal(localeString, displayLocale);
    }
  
    /**
     * Get the display name of the language in the system's locale.
     * For example in an English system, en_US: "English", fr_CA: "French"
     *
     * @param localeString the locale to display.
     * @return the display name of the language.
     */
    public static String getLanguageDisplayNameInSystemLocale(
        final String localeString) {
      final Locale displayLocale = sResources.getConfiguration().locale;
      final String languageString;
      if (sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) {
        languageString = localeString;
      } else {
        languageString = LocaleUtils.constructLocaleFromString(localeString).getLanguage();
      }
      return getLocaleDisplayNameInternal(languageString, displayLocale);
    }
  
    /**
     * Get the display name of the language in its locale.
     * For example, en_US: "English", fr_CA: "Français"
     *
     * @param localeString the locale to display.
     * @return the display name of the language.
     */
    public static String getLanguageDisplayNameInLocale(final String localeString) {
      final Locale displayLocale = getDisplayLocale(localeString);
      final String languageString;
      if (sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) {
        languageString = localeString;
      } else {
        languageString = LocaleUtils.constructLocaleFromString(localeString).getLanguage();
      }
      return getLocaleDisplayNameInternal(languageString, displayLocale);
    }
  
    private static String getLocaleDisplayNameInternal(final String localeString,
                                                       final Locale displayLocale) {
      final Integer exceptionalNameResId;
      if (displayLocale.equals(Locale.ROOT)
          && sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) {
        exceptionalNameResId = sExceptionalLocaleDisplayedInRootLocale.get(localeString);
      } else if (sExceptionalLocaleToNameIdsMap.containsKey(localeString)) {
        exceptionalNameResId = sExceptionalLocaleToNameIdsMap.get(localeString);
      } else {
        exceptionalNameResId = null;
      }
  
      final String displayName;
      if (exceptionalNameResId != null) {
        displayName = String.valueOf(sResources.getString(exceptionalNameResId));
      } else {
        displayName = LocaleUtils.constructLocaleFromString(localeString)
            .getDisplayName(displayLocale);
      }
      return StringUtils.capitalizeFirstCodePoint(displayName, displayLocale);
    }
  }
  