/*
 * Copyright 2009 Google Inc.
 * 
 * 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.google.gwt.i18n.server;

import com.google.gwt.i18n.shared.GwtLocale;
import com.google.gwt.i18n.shared.GwtLocaleFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Class representing GWT locales and conversion to/from other formats.
 * 
 * These locales correspond to BCP47.
 */
public class GwtLocaleImpl implements GwtLocale {
  // TODO(jat): implement a version of this suitable for client-side use,
  // probably using a generator to include only the information relevant to
  // the set of locales supported, and then figure out a way to get that into
  // the property provider to handle inheritance there.

  /**
   * Maps deprecated language codes to the canonical code.  Strings are always
   * in pairs, with the first being the canonical code and the second being
   * a deprecated code which maps to it.
   * 
   * Source: http://www.loc.gov/standards/iso639-2/php/code_changes.php
   * 
   * TODO: consider building maps if this list grows much.
   */
  private static final String[] deprecatedLanguages = new String[] {
    "he", "iw",   // Hebrew
    "id", "in",   // Indonesian 
    "jv", "jw",   // Javanese, typo in original publication 
    "ro", "mo",   // Moldovian
    "yi", "ji",   // Yiddish
  };

  /**
   * Maps deprecated region codes to the canonical code.  Strings are always
   * in pairs, with the first being the canonical code and the second being
   * a deprecated code which maps to it.
   * 
   * Note that any mappings which split an old code into multiple new codes
   * cannot be done automatically (such as cs -> rs/me) -- perhaps we could
   * have a way of flagging region codes which are no longer valid and allow
   * an appropriate warning message.
   * 
   * Source: http://en.wikipedia.org/wiki/ISO_3166-1
   * 
   * TODO: consider building maps if this list grows much.
   */
  private static final String[] deprecatedRegions = new String[] {
    // East Timor - http://www.iso.org/iso/newsletter_v-5_east_timor.pdf
    "TL", "TP",
  };

  /**
   * Add in the missing locale of a deprecated pair.
   * 
   * @param factory GwtLocaleFactory to create new instances with
   * @param locale locale to add deprecated pair for
   * @param aliases where to store the alias if present
   */
  private static void addDeprecatedPairs(GwtLocaleFactory factory,
      GwtLocale locale, List<GwtLocale> aliases) {
    int n = deprecatedLanguages.length;
    for (int i = 0; i < n; i += 2) {
      if (deprecatedLanguages[i].equals(locale.getLanguage())) {
        aliases.add(factory.fromComponents(deprecatedLanguages[i + 1],
            locale.getScript(), locale.getRegion(), locale.getVariant()));
        break;
      }
      if (deprecatedLanguages[i + 1].equals(locale.getLanguage())) {
        aliases.add(factory.fromComponents(deprecatedLanguages[i],
            locale.getScript(), locale.getRegion(), locale.getVariant()));
        break;
      }
    }
  }

  private static void addImmediateParentRegions(GwtLocaleFactory factory,
      GwtLocale locale, Collection<GwtLocale> work) {
    String language = locale.getLanguage();
    String script = locale.getScript();
    String region = locale.getRegion();
    String variant = locale.getVariant();
    if (variant != null) {
      work.add(factory.fromComponents(language, script, region, null));
    }
    Set<String> immediateParents = RegionInheritance.getImmediateParents(region);
    for (String parent : immediateParents) {
      work.add(factory.fromComponents(language, script, parent, variant));
      if (variant != null) {
        work.add(factory.fromComponents(language, script, parent, null));
      }
    }
    if (immediateParents.isEmpty()) {
      work.add(factory.fromComponents(language, script, null, variant));
      if (variant != null) {
        work.add(factory.fromComponents(language, script, null, null));
      }
    }
    if (script != null) {
      work.add(factory.fromComponents(language, null, region, variant));
      if (variant != null) {
        work.add(factory.fromComponents(language, null, region, null));
      }
    }
  }

  /**
   * Add inherited regions for a given locale.
   * 
   * @param factory
   * @param inherits
   * @param language
   * @param script
   * @param region
   * @param variant
   */
  private static void addParentRegionLocales(GwtLocaleFactory factory,
      List<GwtLocale> inherits, String language, String script, String region,
      String variant) {
    for (String parent : RegionInheritance.getAllAncestors(region)) {
      inherits.add(factory.fromComponents(language, script, parent, variant));
    }
  }

  /**
   * Add special aliases for a given locale.
   * 
   * This includes things like choosing the default script/region for Chinese
   * based on the other one, handling Norwegian language changes, and treating
   * pt_BR as the default pt type.
   * 
   * @param factory GwtLocaleFactory to create new instances with
   * @param locale locale to add deprecated pair for
   * @param aliases where to store the alias if present
   */
  private static void addSpecialAliases(GwtLocaleFactory factory,
      GwtLocale locale, List<GwtLocale> aliases) {
    String language = locale.getLanguage();
    String script = locale.getScript();
    String region = locale.getRegion();
    String variant = locale.getVariant();
    if ("zh".equals(language)) {
      if (script == null) {
        // infer script from region
        if ("TW".equals(region)) {
          aliases.add(factory.fromComponents("zh", "Hant", region, variant));
        } else if ("CN".equals(region)) {
          aliases.add(factory.fromComponents("zh", "Hans", region, variant));
        }
      } else {
        if (region == null) {
          // Add aliases for main users of particular scripts
          aliases.add(factory.fromComponents("zh", script,
              "Hant".equals(script) ? "TW" : "CN", variant));
        }
      }
    } else if ("no".equals(language)) {
      if (variant == null || "BOKMAL".equals(variant)) {
        aliases.add(factory.fromComponents("nb", script, region, null));
        aliases.add(factory.fromComponents("no-bok", script, region, null));
      } else if ("NYNORSK".equals(variant)) {
        aliases.add(factory.fromComponents("nn", script, region, null));
        aliases.add(factory.fromComponents("no-nyn", script, region, null));
      }
    } else if ("nb".equals(language)) {
      aliases.add(factory.fromComponents("no", script, region, "BOKMAL"));
    } else if ("nn".equals(language)) {
      aliases.add(factory.fromComponents("no", script, region, "NYNORSK"));
    } else if ("pt".equals(language)) {
      if (region == null) {
        aliases.add(factory.fromComponents("pt", script, "BR", variant));
      } else if ("BR".equals(region)) {
        aliases.add(factory.fromComponents("pt", script, null, variant));
      }
    }
  }

  private static boolean equalsNullCheck(String str1, String str2) {
    if (str1 == null) {
      return str2 == null;
    }
    return str1.equals(str2);
  }

  /**
   * Compare strings, accounting for nulls (which are treated as before any
   * other value).
   * 
   * @param a first string
   * @param b second string
   * 
   * @return positive if a>b, negative if a<b, 0 if equal
   */
  private static int stringCompare(String a, String b) {
    if (a == null) {
      return b == null ? 0 : -1;
    }
    if (b == null) {
      return 1;
    }
    return a.compareTo(b);
  }

  private final GwtLocaleFactory factory;

  private final String language;

  private final String region;

  private final String script;

  private final String variant;

  private ArrayList<GwtLocale> cachedSearchList;

  private ArrayList<GwtLocale> cachedAliases;

  /**
   * Must only be called from a factory to preserve instance caching.
   */
  GwtLocaleImpl(GwtLocaleFactory factory, String language, String region,
      String script, String variant) {
    this.factory = factory;
    this.language = language;
    this.region = region;
    this.script = script;
    this.variant = variant;
  }

  public int compareTo(GwtLocale o) {
    int c = stringCompare(language, o.getLanguage());
    if (c == 0) {
      c = stringCompare(script, o.getScript());
    }
    if (c == 0) {
      c = stringCompare(region, o.getRegion());
    }
    if (c == 0) {
      c = stringCompare(variant, o.getVariant());
    }
    return c;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!(obj instanceof GwtLocale)) {
      return false;
    }
    GwtLocale other = (GwtLocale) obj;
    return equalsNullCheck(language, other.getLanguage())
        && equalsNullCheck(region, other.getRegion())
        && equalsNullCheck(script, other.getScript())
        && equalsNullCheck(variant, other.getVariant());
  }

  public List<GwtLocale> getAliases() {
    // TODO(jat): more locale aliases? better way to encode them?
    if (cachedAliases == null) {
      cachedAliases = new ArrayList<GwtLocale>();
      GwtLocale canonicalForm = getCanonicalForm();
      Set<GwtLocale> seen = new HashSet<GwtLocale>();
      cachedAliases.add(canonicalForm);
      ArrayList<GwtLocale> nextGroup = new ArrayList<GwtLocale>();
      nextGroup.add(this);
      // Account for default script
      String defaultScript = DefaultLanguageScripts.getDefaultScript(language);
      if (defaultScript != null) {
        if (script == null) {
          nextGroup.add(factory.fromComponents(language, defaultScript, region,
              variant));
        } else if (script.equals(defaultScript)) {
          nextGroup.add(factory.fromComponents(language, null, region, variant));
        }
      }
      while (!nextGroup.isEmpty()) {
        List<GwtLocale> thisGroup = nextGroup;
        nextGroup = new ArrayList<GwtLocale>();
        for (GwtLocale locale : thisGroup) {
          if (seen.contains(locale)) {
            continue;
          }
          seen.add(locale);
          if (!locale.equals(canonicalForm)) {
            cachedAliases.add(locale);
          }
          addDeprecatedPairs(factory, locale, nextGroup);
          addSpecialAliases(factory, locale, nextGroup);
        }
      }
    }
    return Collections.unmodifiableList(cachedAliases);
  }

  public String getAsString() {
    StringBuilder buf = new StringBuilder();
    if (language != null) {
      buf.append(language);
    }
    if (script != null) {
      buf.append('_');
      buf.append(script);
    }
    if (region != null) {
      buf.append('_');
      buf.append(region);
    }
    if (variant != null) {
      buf.append('_');
      buf.append(variant);
    }
    return buf.toString();
  }

  /**
   * Returns this locale in canonical form.  Changes for canonical form are:
   * <ul>
   *  <li>Deprecated language/region tags are replaced with official versions
   * </ul>
   * 
   * @return GwtLocale instance 
   */
  public GwtLocale getCanonicalForm() {
    String canonLanguage = language;
    String canonScript = script;
    String canonRegion = region;
    String canonVariant = variant;
    // Handle deprecated language codes
    int n = deprecatedLanguages.length;
    for (int i = 0; i < n; i += 2) {
      if (deprecatedLanguages[i + 1].equals(canonLanguage)) {
        canonLanguage = deprecatedLanguages[i];
        break;
      }
    }
    // Handle deprecated region codes
    n = deprecatedRegions.length;
    for (int i = 0; i < n; i += 2) {
      if (deprecatedRegions[i + 1].equals(canonRegion)) {
        canonRegion = deprecatedRegions[i];
        break;
      }
    }
    // Special-case Chinese default scripts
    if ("zh".equals(canonLanguage)) {
      if (canonRegion != null) {
        if ("CN".equals(canonRegion) && "Hans".equals(canonScript)) {
          canonScript = null;
        } else if ("TW".equals(canonRegion) && "Hant".equals(canonScript)) {
          canonScript = null;
        }
      } else if ("Hans".equals(canonScript)) {
        canonRegion = "CN";
        canonScript = null;
      } else if ("Hant".equals(canonScript)) {
        canonRegion = "TW";
        canonScript = null;
      }
    }
    // Special-case no->nb/nn split
    if ("no-bok".equals(canonLanguage)) {
      canonLanguage = "nb";
      canonVariant = null;
    } else if ("no-nyn".equals(canonLanguage)) {
      canonLanguage = "nn";
      canonVariant = null;
    } else if ("no".equals(canonLanguage)) {
      if (canonVariant == null || "BOKMAL".equals(canonVariant)) {
        canonLanguage = "nb";
        canonVariant = null;
      } else if ("NYNORSK".equals(canonVariant)) {
        canonLanguage = "nn";
        canonVariant = null;
      }
    }
    // Remove any default script for the language
    if (canonScript != null && canonScript.equals(
        DefaultLanguageScripts.getDefaultScript(canonLanguage))) {
      canonScript = null;
    }
    return factory.fromComponents(canonLanguage, canonScript, canonRegion,
        canonVariant);
  }

  public List<GwtLocale> getCompleteSearchList() {
    // TODO(jat): get zh_Hant to come before zh in search list for zh_TW
    if (cachedSearchList == null) {
      cachedSearchList = new ArrayList<GwtLocale>();
      Set<GwtLocale> seen = new HashSet<GwtLocale>();
      List<GwtLocale> thisGroup = new ArrayList<GwtLocale>(this.getAliases());
      seen.addAll(thisGroup);
      GwtLocale defLocale = factory.getDefault();
      seen.add(defLocale);
      while (!thisGroup.isEmpty()) {
        cachedSearchList.addAll(thisGroup);
        List<GwtLocale> nextGroup = new ArrayList<GwtLocale>();
        for (GwtLocale locale : thisGroup) {
          List<GwtLocale> work = new ArrayList<GwtLocale>(locale.getAliases());
          work.removeAll(seen);
          nextGroup.addAll(work);
          seen.addAll(work);
          work.clear();
          if (locale.getRegion() != null) {
            addImmediateParentRegions(factory, locale, work);
          } else if (locale.getVariant() != null) {
            work.add(factory.fromComponents(locale.getLanguage(),
                locale.getScript(), null, null));
          } else if (locale.getScript() != null) {
            work.add(factory.fromComponents(locale.getLanguage(), null, null,
                null));
          }
          work.removeAll(seen);
          nextGroup.addAll(work);
          seen.addAll(work);
        }
        thisGroup = nextGroup;
      }
      if (!isDefault()) {
        cachedSearchList.add(defLocale);
      }
    }
    return cachedSearchList;
  }

  /**
   * Return a list of locales to search for, in order of preference.  The
   * current locale is always first on the list.  Aliases are not included
   * in the list -- use {@link #getAliases} to expand those.
   * 
   * @return inheritance list
   */
  public List<GwtLocale> getInheritanceChain() {
    List<GwtLocale> inherits = new ArrayList<GwtLocale>();
    inherits.add(this);
    if (variant != null) {
      inherits.add(factory.fromComponents(language, script, region, null));
    }
    if (region != null) {
      addParentRegionLocales(factory, inherits, language, script, region,
          null);
      inherits.add(factory.fromComponents(language, script, null, null));
    }
    if (script != null) {
      inherits.add(factory.fromComponents(language, null, region, null));
      addParentRegionLocales(factory, inherits, language, null, region, null);
      if (region != null) {
        inherits.add(factory.fromComponents(language, null, null, null));
      }
    }
    if (language != null) {
      inherits.add(factory.fromComponents(null, null, null, null));
    }
    return inherits;
  }

  public String getLanguage() {
    return language;
  }

  public String getLanguageNotNull() {
    return language == null ? "" : language;
  }

  public String getRegion() {
    return region;
  }

  public String getRegionNotNull() {
    return region == null ? "" : region;
  }

  public String getScript() {
    return script;
  }

  public String getScriptNotNull() {
    return script == null ? "" : script;
  }

  public String getVariant() {
    return variant;
  }

  public String getVariantNotNull() {
    return variant == null ? "" : variant;
  }

  @Override
  public int hashCode() {
    int result = ((language == null) ? 0 : language.hashCode());
    result = 37 * result + ((region == null) ? 0 : region.hashCode());
    result = 43 * result + ((script == null) ? 0 : script.hashCode());
    result = 53 * result + ((variant == null) ? 0 : variant.hashCode());
    return result;
  }

  /**
   * Return true if this locale inherits from the specified locale.  Note that
   * locale.inheritsFrom(locale) is false -- if you want that to be true, you
   * should just use locale.getInheritanceChain().contains(x).
   * 
   * @param parent locale to test against
   * @return true if parent is an ancestor of this locale
   */
  public boolean inheritsFrom(GwtLocale parent) {
    if (equals(parent)) {
      return false;
    }
    return getInheritanceChain().contains(parent);
  }

  public boolean isDefault() {
    return language == null;
  }

  @Override
  public String toString() {
    if (language == null) {
      return DEFAULT_LOCALE;
    }
    return getAsString();
  }

  /**
   * Checks if this locale uses the same script as another locale, taking into
   * account default scripts.
   * 
   * @param other
   * @return true if the scripts are the same
   */
  public boolean usesSameScript(GwtLocale other) {
    // The number of aliases is very small, so n^2 isn't a problem here.
    List<GwtLocale> myAliases = getAliases();
    List<GwtLocale> otherAliases = other.getAliases();
    for (GwtLocale alias : myAliases) {
      for (GwtLocale otherAlias : otherAliases) {
        if (equalsNullCheck(alias.getScript(), otherAlias.getScript())) {
          return true;
        }
      }
    }
    return false;
  }
}
