content: /*
   * Copyright (C) 2018 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.android.server.textservices;
  
  import android.annotation.Nullable;
  import android.text.TextUtils;
  
  import java.util.ArrayList;
  import java.util.Locale;
  
  /**
   * Provides {@code Locale} related utility methods for {@link TextServicesManagerService}.
   * <p>This class is intentionally package-private.  Utility methods here are tightly coupled with
   * implementation details in {@link TextServicesManagerService}.  Hence this class is not suitable
   * for other components to directly use.</p>
   */
  final class LocaleUtils {
      /**
       * Returns a list of {@link Locale} in the order of appropriateness for the default spell
       * checker service.
       *
       * <p>If the system language is English, and the region is also explicitly specified in the
       * system locale, the following fallback order will be applied.</p>
       * <ul>
       * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li>
       * <li>(system-locale-language, system-locale-region)</li>
       * <li>("en", "US")</li>
       * <li>("en", "GB")</li>
       * <li>("en")</li>
       * </ul>
       *
       * <p>If the system language is English, but no region is specified in the system locale,
       * the following fallback order will be applied.</p>
       * <ul>
       * <li>("en")</li>
       * <li>("en", "US")</li>
       * <li>("en", "GB")</li>
       * </ul>
       *
       * <p>If the system language is not English, the following fallback order will be applied.</p>
       * <ul>
       * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li>
       * <li>(system-locale-language, system-locale-region) (if exists)</li>
       * <li>(system-locale-language) (if exists)</li>
       * <li>("en", "US")</li>
       * <li>("en", "GB")</li>
       * <li>("en")</li>
       * </ul>
       *
       * @param systemLocale the current system locale to be taken into consideration.
       * @return a list of {@link Locale}. The first one is considered to be most appropriate.
       */
      public static ArrayList<Locale> getSuitableLocalesForSpellChecker(
              @Nullable final Locale systemLocale) {
          final Locale systemLocaleLanguageCountryVariant;
          final Locale systemLocaleLanguageCountry;
          final Locale systemLocaleLanguage;
          if (systemLocale != null) {
              final String language = systemLocale.getLanguage();
              final boolean hasLanguage = !TextUtils.isEmpty(language);
              final String country = systemLocale.getCountry();
              final boolean hasCountry = !TextUtils.isEmpty(country);
              final String variant = systemLocale.getVariant();
              final boolean hasVariant = !TextUtils.isEmpty(variant);
              if (hasLanguage && hasCountry && hasVariant) {
                  systemLocaleLanguageCountryVariant = new Locale(language, country, variant);
              } else {
                  systemLocaleLanguageCountryVariant = null;
              }
              if (hasLanguage && hasCountry) {
                  systemLocaleLanguageCountry = new Locale(language, country);
              } else {
                  systemLocaleLanguageCountry = null;
              }
              if (hasLanguage) {
                  systemLocaleLanguage = new Locale(language);
              } else {
                  systemLocaleLanguage = null;
              }
          } else {
              systemLocaleLanguageCountryVariant = null;
              systemLocaleLanguageCountry = null;
              systemLocaleLanguage = null;
          }
  
          final ArrayList<Locale> locales = new ArrayList<>();
          if (systemLocaleLanguageCountryVariant != null) {
              locales.add(systemLocaleLanguageCountryVariant);
          }
  
          if (Locale.ENGLISH.equals(systemLocaleLanguage)) {
              if (systemLocaleLanguageCountry != null) {
                  // If the system language is English, and the region is also explicitly specified,
                  // following fallback order will be applied.
                  // - systemLocaleLanguageCountry [if systemLocaleLanguageCountry is non-null]
                  // - en_US [if systemLocaleLanguageCountry is non-null and not en_US]
                  // - en_GB [if systemLocaleLanguageCountry is non-null and not en_GB]
                  // - en
                  if (systemLocaleLanguageCountry != null) {
                      locales.add(systemLocaleLanguageCountry);
                  }
                  if (!Locale.US.equals(systemLocaleLanguageCountry)) {
                      locales.add(Locale.US);
                  }
                  if (!Locale.UK.equals(systemLocaleLanguageCountry)) {
                      locales.add(Locale.UK);
                  }
                  locales.add(Locale.ENGLISH);
              } else {
                  // If the system language is English, but no region is specified, following
                  // fallback order will be applied.
                  // - en
                  // - en_US
                  // - en_GB
                  locales.add(Locale.ENGLISH);
                  locales.add(Locale.US);
                  locales.add(Locale.UK);
              }
          } else {
              // If the system language is not English, the fallback order will be
              // - systemLocaleLanguageCountry  [if non-null]
              // - systemLocaleLanguage  [if non-null]
              // - en_US
              // - en_GB
              // - en
              if (systemLocaleLanguageCountry != null) {
                  locales.add(systemLocaleLanguageCountry);
              }
              if (systemLocaleLanguage != null) {
                  locales.add(systemLocaleLanguage);
              }
              locales.add(Locale.US);
              locales.add(Locale.UK);
              locales.add(Locale.ENGLISH);
          }
          return locales;
      }
  }
  