/*
 * Copyright 2010 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.tools.cldr;

import com.google.gwt.i18n.shared.GwtLocale;
import com.google.gwt.tools.cldr.RegionLanguageData.RegionPopulation;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.CollationKey;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

/**
 * Extract localized names from CLDR data.
 */
public class LocalizedNamesProcessor extends Processor {

  private static class IndexedName implements Comparable<IndexedName> {

    private final int index;
    private final CollationKey key;

    public IndexedName(Collator collator, int index, String value) {
      this.index = index;
      this.key = collator.getCollationKey(value);
    }

    @Override
    public int compareTo(IndexedName o) {
      return key.compareTo(o.key);
    }

    /**
     * @return index of this name.
     */
    public int getIndex() {
      return index;
    }
  }

  /**
   * Split a list of region codes into an array.
   * 
   * @param regionList comma-separated list of region codes
   * @return array of region codes, null if none
   */
  private static String[] getRegionOrder(String regionList) {
    String[] split = null;
    if (regionList != null && regionList.length() > 0) {
      split = regionList.split(",");
    }
    return split;
  }

  private final RegionLanguageData regionLanguageData;

  public LocalizedNamesProcessor(File outputDir, InputFactory cldrFactory, LocaleData localeData) {
    super(outputDir, cldrFactory, localeData);
    regionLanguageData = new RegionLanguageData(cldrFactory);
  }

  @Override
  protected void cleanupData() {
    localeData.copyLocaleData("en", "default", "territory", "languages", "scripts", "variants");
    // Generate a sort order before removing duplicates
    for (GwtLocale locale : localeData.getNonEmptyLocales("territory")) {
      // TODO(jat): deal with language population data that has a script
      Map<String, String> map = localeData.getEntries("territory", locale);
      List<String> countryCodes = new ArrayList<String>();
      for (String regionCode : map.keySet()) {
        // only include real country codes
        if (!"ZZ".equals(regionCode) && regionCode.length() == 2) {
          countryCodes.add(regionCode);
        }
      }
      Locale javaLocale =
          new Locale(locale.getLanguageNotNull(), locale.getRegionNotNull(), locale
              .getVariantNotNull());
      Collator collator = Collator.getInstance(javaLocale);
      IndexedName[] names = new IndexedName[countryCodes.size()];
      for (int i = 0; i < names.length; ++i) {
        names[i] = new IndexedName(collator, i, map.get(countryCodes.get(i)));
      }
      Arrays.sort(names);
      StringBuilder buf = new StringBuilder();
      boolean first = true;
      for (int i = 0; i < names.length; ++i) {
        if (first) {
          first = false;
        } else {
          buf.append(',');
        }
        buf.append(countryCodes.get(names[i].getIndex()));
      }
      localeData.addEntry("territory", locale, "!sortorder", buf.toString());
    }
    for (GwtLocale locale : localeData.getAllLocales()) {
      Set<RegionPopulation> regions = getRegionsForLocale(locale);
      StringBuilder buf = new StringBuilder();
      if (!locale.isDefault()) {
        int count = 0;
        for (RegionPopulation region : regions) {
          // only keep the first 10, and stop if there aren't many speakers
          if (++count > 10 || region.getLiteratePopulation() < 3000000) {
            break;
          }
          if (count > 1) {
            buf.append(',');
          }
          buf.append(region.getRegion());
        }
      }
      localeData.addEntry("territory", locale, "!likelyorder", buf.toString());
    }
    localeData.removeDuplicates("territory");
    localeData.removeDuplicates("language");
    localeData.removeDuplicates("script");
    localeData.removeDuplicates("variant");
  }

  @Override
  protected void loadData() throws IOException {
    System.out.println("Loading data for localized names");
    localeData.addVersions(cldrFactory);
    localeData.addEntries("territory", cldrFactory, "//ldml/localeDisplayNames/territories",
        "territory", "type");
    localeData.addEntries("language", cldrFactory, "//ldml/localeDisplayNames/languages",
        "language", "type");
    localeData.addEntries("script", cldrFactory, "//ldml/localeDisplayNames/scripts", "script",
        "type");
    localeData.addEntries("variant", cldrFactory, "//ldml/localeDisplayNames/variants", "variant",
        "type");
  }

  @Override
  protected void writeOutputFiles() throws IOException {
    Set<GwtLocale> localesToPrint = localeData.getNonEmptyLocales("territory");
    String cldrDir = "client/impl/cldr/";
    writeVersionFile(cldrDir + "LocalizedNames.versions.txt", localesToPrint);

    for (GwtLocale locale : localesToPrint) {
      Map<String, String> namesMap = localeData.getEntries("territory", locale);
      List<String> regionCodesWithNames = new ArrayList<String>();
      for (String regionCode : namesMap.keySet()) {
        if (!regionCode.startsWith("!")) {
          // skip entries which aren't actually region codes
          regionCodesWithNames.add(regionCode);
        }
      }
      String[] sortOrder = getRegionOrder(namesMap.get("!sortorder"));
      String[] likelyOrder = getRegionOrder(namesMap.get("!likelyorder"));
      if (regionCodesWithNames.isEmpty() && sortOrder == null && likelyOrder == null) {
        // nothing to do
        return;
      }
      // sort for deterministic output
      Collections.sort(regionCodesWithNames);
      if (locale.isDefault()) {
        generateDefaultLocale("client/DefaultLocalizedNames.java",
            locale, namesMap, regionCodesWithNames, sortOrder, likelyOrder);
      }

      // Choose filename
      String localePart = locale.getAsString();
      if (localePart == null || localePart.isEmpty()) {
        localePart = "";
      } else {
        localePart = "_" + localePart;
      }
      String path = cldrDir + "LocalizedNamesImpl" + localePart + "." + "java";

      generateLocale(path, locale, namesMap, regionCodesWithNames, sortOrder, likelyOrder);
    }
  }

  private void generateDefaultLocale(String path, GwtLocale locale, Map<String, String> namesMap,
      List<String> regionCodesWithNames, String[] sortOrder, String[] likelyOrder)
      throws IOException {
    PrintWriter pw = null;
    try {
      pw = createOutputFile(path);
      printHeader(pw);
      pw.println("package com.google.gwt.i18n.client;");
      pw.println();
      printVersion(pw, locale, "// ");
      pw.println();
      pw.println("/**");
      pw.println(" * Default LocalizedNames implementation.");
      pw.println(" */");
      pw.print("public class DefaultLocalizedNames extends " + "DefaultLocalizedNamesBase {");
      if (likelyOrder != null) {
        writeStringListMethod(pw, "loadLikelyRegionCodes", likelyOrder);
      }
      pw.println();
      pw.println("  @Override");
      pw.println("  protected void loadNameMap() {");
      pw.println("    super.loadNameMap();");
      for (String code : regionCodesWithNames) {
        String name = namesMap.get(code);
        if (name != null) {
          pw.println("    namesMap.put(\"" + quote(code) + "\", \"" + quote(name) + "\");");
        }
      }
      pw.println("  }");
      if (sortOrder != null) {
        writeStringListMethod(pw, "loadSortedRegionCodes", sortOrder);
      }
      pw.println("}");
    } finally {
      if (pw != null) {
        pw.close();
      }
    }
  }

  private void generateLocale(String path, GwtLocale locale, Map<String, String> namesMap,
      List<String> regionCodesWithNames, String[] sortOrder, String[] likelyOrder)
      throws IOException {
    PrintWriter pw = null;
    try {
      pw = createOutputFile(path);
      printHeader(pw);
      pw.println("package com.google.gwt.i18n.client.impl.cldr;");
      pw.println();
      if (!regionCodesWithNames.isEmpty()) {
        pw.println("import com.google.gwt.core.client.JavaScriptObject;");
        pw.println();
      }
      printVersion(pw, locale, "// ");
      pw.println();
      pw.println("/**");
      pw.println(" * Localized names for the \"" + locale + "\" locale.");
      pw.println(" */");
      pw.print("public class LocalizedNamesImpl" + localeSuffix(locale) + " extends ");
      if (locale.isDefault()) {
        pw.print("LocalizedNamesImplBase");
      } else {
        pw.print("LocalizedNamesImpl" + localeSuffix(localeData.inheritsFrom(locale)));
      }
      pw.println(" {");
      if (!locale.isDefault()) {
        if (likelyOrder != null) {
          writeStringListMethod(pw, "loadLikelyRegionCodes", likelyOrder);
        }
        if (sortOrder != null) {
          writeStringListMethod(pw, "loadSortedRegionCodes", sortOrder);
        }
        if (!regionCodesWithNames.isEmpty()) {
          pw.println();
          pw.println("  @Override");
          pw.println("  protected void loadNameMapJava() {");
          pw.println("    super.loadNameMapJava();");
          for (String code : regionCodesWithNames) {
            String name = namesMap.get(code);
            if (name != null && !name.equals(code)) {
              pw.println("    namesMap.put(\"" + quote(code) + "\", \"" + quote(name) + "\");");
            }
          }
          pw.println("  }");
          pw.println();
          pw.println("  @Override");
          pw.println("  protected JavaScriptObject loadNameMapNative() {");
          pw.println("    return overrideMap(super.loadNameMapNative(), " + "loadMyNameMap());");
          pw.println("  }");
          pw.println();
          pw.println("  private native JavaScriptObject loadMyNameMap() /*-{");
          generateNativeMap(pw, regionCodesWithNames, namesMap);
          pw.println("  }-*/;");
        }
      } else if (!regionCodesWithNames.isEmpty()) {
        pw.println();
        pw.println("  @Override");
        pw.println("  protected native JavaScriptObject loadNameMapNative() " + "/*-{");
        generateNativeMap(pw, regionCodesWithNames, namesMap);
        pw.println("  }-*/;");
      }
      pw.println("}");
    } finally {
      if (pw != null) {
        pw.close();
      }
    }
  }

  /**
   * @param regionCodesWithNames
   * @param namesMap
   */
  private void generateNativeMap(PrintWriter pw, List<String> regionCodesWithNames,
      Map<String, String> namesMap) {
    pw.println("    return {");
    boolean firstLine = true;
    for (String code : regionCodesWithNames) {
      String name = namesMap.get(code);
      if (name != null && !name.equals(code)) {
        if (firstLine) {
          firstLine = false;
        } else {
          pw.println(",");
        }
        pw.print("        \"" + quote(code) + "\": \"" + quote(name) + "\"");
      }
    }
    pw.println();
    pw.println("    };");
  }

  /**
   * @param locale
   * @return region populations speaking this language
   */
  private Set<RegionPopulation> getRegionsForLocale(GwtLocale locale) {
    Set<RegionPopulation> retVal =
        regionLanguageData
            .getRegions(locale.getLanguageNotNull() + "_" + locale.getScriptNotNull());
    if (retVal.isEmpty()) {
      retVal = regionLanguageData.getRegions(locale.getLanguageNotNull());
    }
    return retVal;
  }

  /**
   * Generate a method which returns an array of string constants.
   * 
   * @param pw PrintWriter to write on
   * @param methodName the name of the method to create
   * @param values the list of string values to return.
   */
  private void writeStringListMethod(PrintWriter pw, String methodName, String[] values) {
    pw.println();
    pw.println("  @Override");
    pw.println("  public String[] " + methodName + "() {");
    pw.println("    return new String[] {");
    for (String code : values) {
      pw.println("        \"" + Processor.quote(code) + "\",");
    }
    pw.println("    };");
    pw.println("  }");
  }
}
