/*
 * 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.codegen.server.StringGenerator;
import com.google.gwt.i18n.rebind.DateTimePatternGenerator;
import com.google.gwt.i18n.server.MessageFormatUtils.ArgumentChunk;
import com.google.gwt.i18n.server.MessageFormatUtils.DefaultTemplateChunkVisitor;
import com.google.gwt.i18n.server.MessageFormatUtils.MessageStyle;
import com.google.gwt.i18n.server.MessageFormatUtils.StringChunk;
import com.google.gwt.i18n.server.MessageFormatUtils.TemplateChunk;
import com.google.gwt.i18n.server.MessageFormatUtils.VisitorAbortException;
import com.google.gwt.i18n.shared.DateTimeFormatInfo;
import com.google.gwt.i18n.shared.GwtLocale;
import com.google.gwt.i18n.shared.impl.cldr.DateTimeFormatInfoImpl;

import org.unicode.cldr.util.CLDRFile;
import org.unicode.cldr.util.Factory;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.ParseException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * Loads data needed to produce DateTimeFormatInfo implementations.
 */
public class DateTimeFormatInfoProcessor extends Processor {

  private static final String[] DAYS = new String[] {
      "sun", "mon", "tue", "wed", "thu", "fri", "sat"};

  /**
   * Map of skeleton format patterns and the method name suffix that uses them.
   */
  private static final Map<String, String> FORMATS;

  /**
   * Index of the formats, ordered by the method name.
   */
  private static final SortedMap<String, String> FORMAT_BY_METHOD;

  static {
    FORMATS = new HashMap<String, String>();
    FORMATS.put("d", "Day");
    FORMATS.put("hmm", "Hour12Minute");
    FORMATS.put("hmmss", "Hour12MinuteSecond");
    FORMATS.put("Hmm", "Hour24Minute");
    FORMATS.put("Hmmss", "Hour24MinuteSecond");
    FORMATS.put("mss", "MinuteSecond");
    FORMATS.put("MMM", "MonthAbbrev");
    FORMATS.put("MMMd", "MonthAbbrevDay");
    FORMATS.put("MMMM", "MonthFull");
    FORMATS.put("MMMMd", "MonthFullDay");
    FORMATS.put("MMMMEEEEd", "MonthFullWeekdayDay");
    FORMATS.put("Md", "MonthNumDay");
    FORMATS.put("y", "Year");
    FORMATS.put("yMMM", "YearMonthAbbrev");
    FORMATS.put("yMMMd", "YearMonthAbbrevDay");
    FORMATS.put("yMMMM", "YearMonthFull");
    FORMATS.put("yMMMMd", "YearMonthFullDay");
    FORMATS.put("yM", "YearMonthNum");
    FORMATS.put("yMd", "YearMonthNumDay");
    FORMATS.put("yMMMEEEd", "YearMonthWeekdayDay");
    FORMATS.put("yQQQQ", "YearQuarterFull");
    FORMATS.put("yQ", "YearQuarterShort");

    FORMAT_BY_METHOD = new TreeMap<String, String>();
    for (Map.Entry<String, String> entry : FORMATS.entrySet()) {
      FORMAT_BY_METHOD.put(entry.getValue(), entry.getKey());
    }
  }

  /**
   * Convert the unlocalized name of a day ("sun".."sat") into a day number of
   * the week, ie 0-6.
   * 
   * @param day abbreviated, unlocalized name of the day ("sun".."sat")
   * @return the day number, 0-6
   * @throws IllegalArgumentException if the day name is not found
   */
  private static int getDayNumber(String day) {
    for (int i = 0; i < DAYS.length; ++i) {
      if (DAYS[i].equals(day)) {
        return i;
      }
    }
    throw new IllegalArgumentException();
  }

  private final RegionLanguageData regionLanguageData;

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

  @Override
  protected void cleanupData() {
    System.out.println("Removing duplicates from date/time formats");
    localeData.copyLocaleData("en", "default", "era-wide", "era-abbrev", "quarter-wide",
        "quarter-abbrev", "day-wide", "day-sa-wide", "day-narrow", "day-sa-narrow", "day-abbrev",
        "day-sa-abbrev", "month-wide", "month-sa-wide", "month-narrow", "month-sa-narrow",
        "month-abbrev", "month-sa-abbrev");
    removeUnusedFormats();
    localeData.removeDuplicates("predef");
    localeData.removeDuplicates("weekdata");
    localeData.removeDuplicates("date");
    localeData.removeDuplicates("time");
    localeData.removeDuplicates("dateTime");
    localeData.removeCompleteDuplicates("dayPeriod-abbrev");
    computePeriodRedirects("day");
    computePeriodRedirects("month");
    computePeriodRedirects("day");
    removePeriodDuplicates("day");
    removePeriodDuplicates("month");
    removePeriodDuplicates("quarter");
    removePeriodDuplicates("era");
  }

  /**
   * Generate an override for a method which takes String arguments, which
   * simply redirect to another method based on a default value.
   * 
   * @param pw
   * @param category
   * @param locale
   * @param method
   * @param args
   */
  protected void generateArgMethod(PrintWriter pw, String category, GwtLocale locale,
      String method, String... args) {
    String value = localeData.getEntry(category, locale, "default");
    if (value != null && value.length() > 0) {
      pw.println();
      if (getOverrides()) {
        pw.println("  @Override");
      }
      pw.print("  public String " + method + "(");
      String prefix = "";
      for (String arg : args) {
        pw.print(prefix + "String " + arg);
        prefix = ", ";
      }
      pw.println(") {");
      pw.print("    return " + method + Character.toTitleCase(value.charAt(0)) + value.substring(1)
          + "(");
      prefix = "";
      for (String arg : args) {
        pw.print(prefix + arg);
        prefix = ", ";
      }
      pw.println(");");
      pw.println("  }");
    }
  }

  /**
   * Generate an override for a method which takes String arguments.
   * 
   * @param pw
   * @param category
   * @param locale
   * @param key
   * @param method
   * @param args
   */
  protected void generateArgMethodRedirect(PrintWriter pw, String category, GwtLocale locale,
      String key, String method, final String... args) {
    String value = localeData.getEntry(category, locale, key);
    if (value != null) {
      // cldr data escapes literals with single quote, but we need two single quotes when
      // parsing message formats.
      value = value.replace("'", "''");

      pw.println();
      if (getOverrides()) {
        pw.println("  @Override");
      }
      pw.print("  public String " + method + "(");
      String prefix = "";
      for (String arg : args) {
        pw.print(prefix + "String " + arg);
        prefix = ", ";
      }
      pw.println(") {");
      final StringBuilder buf = new StringBuilder();
      final StringGenerator gen = StringGenerator.create(buf, false);
      try {
        List<TemplateChunk> chunks = MessageStyle.MESSAGE_FORMAT.parse(value);
        for (TemplateChunk chunk : chunks) {
          chunk.accept(new DefaultTemplateChunkVisitor() {
            @Override
            public void visit(ArgumentChunk argChunk) {
              gen.appendStringValuedExpression(args[argChunk.getArgumentNumber()]);
            }

            @Override
            public void visit(StringChunk stringChunk) {
              gen.appendStringLiteral(stringChunk.getString());
            }
          });
        }
      } catch (ParseException e) {
        throw new RuntimeException("Unable to parse pattern '" + value + "' for locale " + locale
            + " key " + category + "/" + key, e);
      } catch (VisitorAbortException e) {
        throw new RuntimeException("Unable to parse pattern '" + value + "' for locale " + locale
            + " key " + category + "/" + key, e);
      }
      gen.completeString();
      pw.println("    return " + buf.toString() + ";");
      pw.println("  }");
    }
  }

  /**
   * Generate a method which returns a day number as an integer.
   * 
   * @param pw
   * @param locale
   * @param key
   * @param method
   */
  protected void generateDayNumber(PrintWriter pw, GwtLocale locale, String key, String method) {
    String day = localeData.getEntry("weekdata", locale, key);
    if (day != null) {
      int value = getDayNumber(day);
      pw.println();
      if (getOverrides()) {
        pw.println("  @Override");
      }
      pw.println("  public int " + method + "() {");
      pw.println("    return " + value + ";");
      pw.println("  }");
    }
  }

  /**
   * Generate a method which returns a format string for a given predefined
   * skeleton pattern.
   * 
   * @param locale
   * @param pw
   * @param skeleton
   * @param methodSuffix
   */
  protected void generateFormat(GwtLocale locale, PrintWriter pw, String skeleton,
      String methodSuffix) {
    String pattern = localeData.getEntry("predef", locale, skeleton);
    generateStringValue(pw, "format" + methodSuffix, pattern);
  }

  /**
   * Generate a series of methods which returns names in wide, narrow, and
   * abbreviated lengths plus their standalone versions.
   * 
   * @param pw
   * @param group
   * @param locale
   * @param methodPrefix
   * @param keys
   */
  protected void generateFullStringList(PrintWriter pw, String group, GwtLocale locale,
      String methodPrefix, String... keys) {
    generateStringListPair(pw, group, locale, methodPrefix, "Full", "wide", keys);
    generateStringListPair(pw, group, locale, methodPrefix, "Narrow", "narrow", keys);
    generateStringListPair(pw, group, locale, methodPrefix, "Short", "abbrev", keys);
  }

  /**
   * Generate an override of a standalone names list that simply redirects to
   * the non-standalone version.
   * 
   * @param pw
   * @param methodPrefix
   */
  protected void generateStandaloneRedirect(PrintWriter pw, String methodPrefix) {
    pw.println();
    if (getOverrides()) {
      pw.println("  @Override");
    }
    pw.println("  public String[] " + methodPrefix + "Standalone" + "() {");
    pw.println("    return " + methodPrefix + "();");
    pw.println("  }");
  }

  /**
   * Generate a method which returns a list of strings.
   * 
   * @param pw
   * @param category
   * @param fallbackCategory
   * @param locale
   * @param method
   * @param keys
   * @return true if the method was skipped as identical to its ancestor
   */
  protected boolean generateStringList(PrintWriter pw, String category, String fallbackCategory,
      GwtLocale locale, String method, String... keys) {
    Map<String, String> map = localeData.getEntries(category, locale);
    Map<String, String> fallback =
        fallbackCategory == null ? Collections.<String, String> emptyMap() : localeData.getEntries(
            fallbackCategory, locale);
    if (map == null || map.isEmpty() && fallback != null && !fallback.isEmpty()) {
      return true;
    }
    if (map != null && !map.isEmpty()) {
      if (fallbackCategory != null) {
        // see if the entry is the same as the fallback
        boolean different = false;
        for (String key : keys) {
          String value = map.get(key);
          if (value != null && !value.equals(fallback.get(key))) {
            different = true;
            break;
          }
        }
        if (!different) {
          return true;
        }
      }
      pw.println();
      if (getOverrides()) {
        pw.println("  @Override");
      }
      pw.println("  public String[] " + method + "() {");
      pw.print("    return new String[] {");
      boolean first = true;
      for (String key : keys) {
        String value = map.get(key);
        if (value == null) {
          value = fallback.get(key);
        }
        if (value == null) {
          System.err.println("Missing \"" + key + "\" in " + locale + "/" + category);
          value = "";
        }
        if (first) {
          first = false;
        } else {
          pw.print(",");
        }
        pw.print("\n        \"" + value.replace("\"", "\\\"") + "\"");
      }
      pw.println("\n    };");
      pw.println("  }");
    }
    return false;
  }

  protected void generateStringListPair(PrintWriter pw, String group, GwtLocale locale,
      String methodPrefix, String width, String categorySuffix, String... keys) {
    generateStringList(pw, group + "-" + categorySuffix, null, locale, methodPrefix + width, keys);
    String redirect =
        localeData.getEntry(group + "-sa-" + categorySuffix + "-redirect", locale, "redirect");
    if ("yes".equals(redirect)) {
      generateStandaloneRedirect(pw, methodPrefix + width);
    } else {
      generateStringList(pw, group + "-sa-" + categorySuffix, group + "-" + categorySuffix, locale,
          methodPrefix + width + "Standalone", keys);
    }
  }

  @Override
  protected void loadData() throws IOException {
    System.out.println("Loading data for date/time formats");
    localeData.addVersions(cldrFactory);
    localeData.addEntries("predef", cldrFactory,
        "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dateTimeFormats/"
            + "availableFormats", "dateFormatItem", "id");
    localeData.addNameEntries("month", cldrFactory);
    localeData.addNameEntries("day", cldrFactory);
    localeData.addNameEntries("quarter", cldrFactory);

    // only add the entries we will use to avoid overriding a parent for
    // differences that don't matter.
    localeData.addEntries("dayPeriod-abbrev", cldrFactory,
        "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dayPeriods/"
            + "dayPeriodContext[@type=\"format\"]/"
            + "dayPeriodWidth[@type=\"abbreviated\"]/dayPeriod[@type=\"am\"]", "dayPeriod", "type");
    localeData.addEntries("dayPeriod-abbrev", cldrFactory,
        "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dayPeriods/"
            + "dayPeriodContext[@type=\"format\"]/"
            + "dayPeriodWidth[@type=\"abbreviated\"]/dayPeriod[@type=\"pm\"]", "dayPeriod", "type");

    localeData.addEntries("era-abbrev", cldrFactory,
        "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/eras/eraAbbr", "era", "type");
    localeData.addEntries("era-wide", cldrFactory,
        "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/eras/eraNames", "era", "type");
    localeData.addDateTimeFormatEntries("date", cldrFactory);
    localeData.addDateTimeFormatEntries("time", cldrFactory);
    localeData.addDateTimeFormatEntries("dateTime", cldrFactory);
    loadWeekData();
    loadFormatPatterns();
  }

  /**
   * Write an output file.
   * 
   * @param locale
   * @param clientShared "client" or "shared", determines the package names
   *     being written to
   * @throws IOException
   * @throws FileNotFoundException
   */
  protected void writeOneOutputFile(GwtLocale locale, String clientShared) throws IOException,
      FileNotFoundException {
    // TODO(jat): make uz_UZ inherit from uz_Cyrl rather than uz, for example
    String myClass;
    String pathSuffix;
    if (locale.isDefault()) {
      if ("client".equals(clientShared)) {
        // The client default is hand-written code that extends the shared one.
        return;
      }
      myClass = "DefaultDateTimeFormatInfo";
      pathSuffix = "/";
    } else {
      myClass = "DateTimeFormatInfoImpl" + localeSuffix(locale);
      pathSuffix = "/impl/cldr/";
    }
    GwtLocale parent = localeData.inheritsFrom(locale);
    PrintWriter pw = createOutputFile(clientShared + pathSuffix + myClass + ".java");
    printHeader(pw);
    pw.print("package com.google.gwt.i18n." + clientShared);
    // GWT now requires JDK 1.6, so we always generate @Overrides
    setOverrides(true);
    if (!locale.isDefault()) {
      pw.print(".impl.cldr");
    }
    pw.println(";");
    pw.println();
    pw.println("// DO NOT EDIT - GENERATED FROM CLDR AND ICU DATA");
    pw.println("//  cldrVersion=" + CLDRFile.GEN_VERSION);
    Map<String, String> map = localeData.getEntries("version", locale);
    for (Map.Entry<String, String> entry : map.entrySet()) {
      pw.println("//  " + entry.getKey() + "=" + entry.getValue());
    }
    pw.println();
    if (locale.isDefault()) {
      pw.println("/**");
      pw.println(" * Default implementation of DateTimeFormatInfo interface, "
          + "using values from");
      pw.println(" * the CLDR root locale.");
      pw.println(" * <p>");
      pw.println(" * Users who need to create their own DateTimeFormatInfo "
          + "implementation are");
      pw.println(" * encouraged to extend this class so their implementation "
          + "won't break when   ");
      pw.println(" * new methods are added.");
      pw.println(" */");
    } else {
      pw.println("/**");
      pw.println(" * Implementation of DateTimeFormatInfo for the \"" + locale + "\" locale.");
      pw.println(" */");
    }
    pw.print("public class " + myClass);
    if (locale.isDefault()) {
      pw.print(" implements " + DateTimeFormatInfo.class.getSimpleName());
    } else {
      pw.print(" extends ");
      pw.print(DateTimeFormatInfoImpl.class.getSimpleName());
      if (!parent.isDefault()) {
        pw.print('_');
        pw.print(parent.getAsString());
      }
    }
    pw.println(" {");

    // write AM/PM names
    generateStringList(pw, "dayPeriod-abbrev", null, locale, "ampms", "am", "pm");

    // write standard date formats
    generateArgMethod(pw, "date", locale, "dateFormat");
    generateStringMethod(pw, "date", locale, "full", "dateFormatFull");
    generateStringMethod(pw, "date", locale, "long", "dateFormatLong");
    generateStringMethod(pw, "date", locale, "medium", "dateFormatMedium");
    generateStringMethod(pw, "date", locale, "short", "dateFormatShort");

    // write methods for assembling date/time formats
    generateArgMethod(pw, "dateTime", locale, "dateTime", "timePattern", "datePattern");
    generateArgMethodRedirect(pw, "dateTime", locale, "full", "dateTimeFull", "timePattern",
        "datePattern");
    generateArgMethodRedirect(pw, "dateTime", locale, "long", "dateTimeLong", "timePattern",
        "datePattern");
    generateArgMethodRedirect(pw, "dateTime", locale, "medium", "dateTimeMedium", "timePattern",
        "datePattern");
    generateArgMethodRedirect(pw, "dateTime", locale, "short", "dateTimeShort", "timePattern",
        "datePattern");

    // write era names
    generateStringList(pw, "era-wide", null, locale, "erasFull", "0", "1");
    generateStringList(pw, "era-abbrev", null, locale, "erasShort", "0", "1");

    // write firstDayOfTheWeek
    generateDayNumber(pw, locale, "firstDay", "firstDayOfTheWeek");

    // write predefined date/time formats
    for (Map.Entry<String, String> entry : FORMAT_BY_METHOD.entrySet()) {
      generateFormat(locale, pw, entry.getValue(), entry.getKey());
    }

    // write month names
    generateFullStringList(pw, "month", locale, "months", "1", "2", "3", "4", "5", "6", "7", "8",
        "9", "10", "11", "12");

    // write quarter names
    generateStringList(pw, "quarter-wide", null, locale, "quartersFull", "1", "2", "3", "4");
    generateStringList(pw, "quarter-abbrev", null, locale, "quartersShort", "1", "2", "3", "4");

    // write standard time formats
    generateArgMethod(pw, "time", locale, "timeFormat");
    generateStringMethod(pw, "time", locale, "full", "timeFormatFull");
    generateStringMethod(pw, "time", locale, "long", "timeFormatLong");
    generateStringMethod(pw, "time", locale, "medium", "timeFormatMedium");
    generateStringMethod(pw, "time", locale, "short", "timeFormatShort");

    // write weekday names
    generateFullStringList(pw, "day", locale, "weekdays", DAYS);

    // write weekend boundaries
    generateDayNumber(pw, locale, "weekendEnd", "weekendEnd");
    generateDayNumber(pw, locale, "weekendStart", "weekendStart");

    pw.println("}");
    pw.close();
  }

  @Override
  protected void writeOutputFiles() throws IOException {
    System.out.println("Writing output for date/time formats");
    for (GwtLocale locale : localeData.getNonEmptyLocales()) {
      // TODO(jat): remove client when we no longer need it
      writeOneOutputFile(locale, "client");
      writeOneOutputFile(locale, "shared");
    }
  }

  /**
   * @param period
   */
  private void computePeriodRedirects(String period) {
    localeData.computeRedirects(period + "-abbrev", period + "-sa-abbrev");
    localeData.computeRedirects(period + "-narrow", period + "-sa-narrow");
    localeData.computeRedirects(period + "-wide", period + "-sa-wide");
  }

  private void loadFormatPatterns() {
    localeData.addEntries("predef", cldrFactory,
        "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dateTimeFormats/"
            + "availableFormats", "dateFormatItem", "id");
    for (GwtLocale locale : localeData.getAllLocales()) {
      DateTimePatternGenerator dtpg = new DateTimePatternGenerator(locale);
      for (Map.Entry<String, String> entry : FORMATS.entrySet()) {
        String skeleton = entry.getKey();
        String cldrPattern = localeData.getEntry("predef", locale, skeleton);
        String pattern = dtpg.getBestPattern(skeleton);
        if (cldrPattern != null && !cldrPattern.equals(pattern)) {
          System.err.println("Mismatch on skeleton pattern in locale " + locale + " for skeleton '"
              + skeleton + "': icu='" + pattern + "', cldr='" + cldrPattern + "'");
        }
        localeData.addEntry("predef", locale, skeleton, pattern);
      }
    }
  }

  /**
   * Load the week start and weekend range values from CLDR.
   */
  private void loadWeekData() {
    localeData.addTerritoryEntries("weekdata", cldrFactory, regionLanguageData,
        "//supplementalData/weekData/firstDay", "firstDay", "day");
    localeData.addTerritoryEntries("weekdata", cldrFactory, regionLanguageData,
        "//supplementalData/weekData/weekendStart", "weekendStart", "day");
    localeData.addTerritoryEntries("weekdata", cldrFactory, regionLanguageData,
        "//supplementalData/weekData/weekendEnd", "weekendEnd", "day");
    localeData.addTerritoryEntries("weekdata", cldrFactory, regionLanguageData,
        "//supplementalData/weekData/minDays", "minDays", "count");
  }

  /**
   * Remove duplicates from period names.
   * 
   * @param group
   */
  private void removePeriodDuplicates(String group) {
    removePeriodWidthDuplicates(group, "wide");
    removePeriodWidthDuplicates(group, "abbrev");
    removePeriodWidthDuplicates(group, "narrow");
  }

  private void removePeriodWidthDuplicates(String group, String width) {
    localeData.removeCompleteDuplicates(group + "-" + width);
    localeData.removeCompleteDuplicates(group + "-sa-" + width);
    localeData.removeCompleteDuplicates(group + "-sa-" + width + "-redirect");
  }

  private void removeUnusedFormats() {
    for (GwtLocale locale : localeData.getAllLocales()) {
      Set<String> toRemove = new HashSet<String>();
      Map<String, String> map = localeData.getEntries("predef", locale);
      for (Entry<String, String> entry : map.entrySet()) {
        if (!FORMATS.containsKey(entry.getKey())) {
          toRemove.add(entry.getKey());
        }
      }
      localeData.removeEntries("predef", locale, toRemove);
    }
  }
}
