/*
 * 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.core.ext.UnableToCompleteException;
import com.google.gwt.i18n.client.DateTimeFormatInfo;
import com.google.gwt.i18n.client.impl.cldr.DateTimeFormatInfoImpl;
import com.google.gwt.i18n.rebind.DateTimePatternGenerator;
import com.google.gwt.i18n.rebind.MessageFormatParser;
import com.google.gwt.i18n.rebind.StringGenerator;
import com.google.gwt.i18n.rebind.MessageFormatParser.ArgumentChunk;
import com.google.gwt.i18n.rebind.MessageFormatParser.DefaultTemplateChunkVisitor;
import com.google.gwt.i18n.rebind.MessageFormatParser.StringChunk;
import com.google.gwt.i18n.rebind.MessageFormatParser.TemplateChunk;
import com.google.gwt.i18n.shared.GwtLocale;

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

import java.io.File;
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.Set;
import java.util.Map.Entry;
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) {
      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 StringBuffer buf = new StringBuffer();
      final StringGenerator gen = new StringGenerator(buf, false);
      try {
        List<TemplateChunk> chunks = MessageFormatParser.parse(value);
        for (TemplateChunk chunk : chunks) {
          chunk.accept(new DefaultTemplateChunkVisitor() {
            @Override
            public void visit(ArgumentChunk argChunk)
                throws UnableToCompleteException {
              gen.appendStringValuedExpression(args[argChunk.getArgumentNumber()]);
            }

            @Override
            public void visit(StringChunk stringChunk)
                throws UnableToCompleteException {
              gen.appendStringLiteral(stringChunk.getString());
            }
          });
        }
      } catch (ParseException e) {
        throw new RuntimeException("Unable to parse pattern '" + value
            + "' for locale " + locale + " key " + category + "/" + key, e);
      } catch (UnableToCompleteException 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.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();
  }

  @Override
  protected void writeOutputFiles() throws IOException {
    // TODO(jat): make uz_UZ inherit from uz_Cyrl rather than uz, for example
    System.out.println("Writing output for date/time formats");
    for (GwtLocale locale : localeData.getNonEmptyLocales()) {
      String myClass;
      String path = "client/";
      String pathSuffix = "";
      if (locale.isDefault()) {
        myClass = "DefaultDateTimeFormatInfo";
      } else {
        myClass = "DateTimeFormatInfoImpl" + localeSuffix(locale);
        pathSuffix = "impl/cldr/";
      }
      GwtLocale parent = localeData.inheritsFrom(locale);
      PrintWriter pw = createOutputFile(path + pathSuffix + myClass + ".java");
      printHeader(pw);
      pw.print("package com.google.gwt.i18n.client");
      if (!locale.isDefault()) {
        pw.print(".impl.cldr");
        setOverrides(true);
      } else {
        setOverrides(false);
      }
      pw.println(";");
      pw.println();
      pw.println("// DO NOT EDIT - GENERATED FROM CLDR AND ICU DATA");
      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();
    }
  }

  /**
   * @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);
    }
  }
}
