/*
 * 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 org.unicode.cldr.util.CLDRFile;
import org.unicode.cldr.util.XPathParts;
import org.unicode.cldr.util.CLDRFile.DraftStatus;
import org.unicode.cldr.util.CLDRFile.Factory;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

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

  private Map<String, Integer> currencyFractions = new HashMap<String, Integer>();
  private int defaultCurrencyFraction;

  private Set<String> stillInUse = new HashSet<String>();

  public CurrencyDataProcessor(File outputDir, Factory cldrFactory,
      LocaleData localeData) {
    super(outputDir, cldrFactory, localeData);
  }

  @Override
  protected void cleanupData() {
    localeData.removeDuplicates("currency");
  }

  @Override
  protected void loadData() throws IOException {
    System.out.println("Loading data for currencies");
    loadLocaleIndependentCurrencyData();
    localeData.addCurrencyEntries("currency", cldrFactory, currencyFractions,
        defaultCurrencyFraction, stillInUse);
  }

  @Override
  protected void printHeader(PrintWriter pw) {
    pw.println("# Do not edit - generated from Unicode CLDR data");
    pw.println("#");
    pw.println("# The key is an ISO4217 currency code, and the value is of the "
        + "form:");
    pw.println("#   display name|symbol|decimal digits|not-used-flag");
    pw.println("# If a symbol is not supplied, the currency code will be used");
    pw.println("# If # of decimal digits is omitted, 2 is used");
    pw.println("# If a currency is not generally used, not-used-flag=1");
    pw.println("# Trailing empty fields can be omitted");
    pw.println();
  }
  
  @Override
  protected void writeOutputFiles() throws IOException {
    for (GwtLocale locale : localeData.getNonEmptyLocales()) {
      String path = "client/impl/cldr/CurrencyData";
      PrintWriter pw = createOutputFile(path + Processor.localeSuffix(locale)
          + ".properties");
      printHeader(pw);
      Map<String, String> map = localeData.getEntries("currency", locale);
      String[] keys = new String[map.size()];
      map.keySet().toArray(keys);
      Arrays.sort(keys);
      
      for (String key : keys) {
        pw.print(key);
        pw.print(" = ");
        pw.println(map.get(key));
      }
      pw.close();
    }
  }

  private void loadLocaleIndependentCurrencyData() {
    CLDRFile supp = cldrFactory.make("supplementalData", true,
        DraftStatus.approved);
    
    // load the table of default # of decimal places for each currency
    currencyFractions = new HashMap<String, Integer>();
    defaultCurrencyFraction = 0;
    XPathParts parts = new XPathParts();
    Iterator<String> iterator = supp.iterator(
        "//supplementalData/currencyData/fractions/info");
    while (iterator.hasNext()) {
      String path = iterator.next();
      parts.set(supp.getFullXPath(path));
      Map<String, String> attr = parts.findAttributes("info");
      if (attr == null) {
        continue;
      }
      String curCode = attr.get("iso4217");
      int digits = Integer.valueOf(attr.get("digits"));
      // TODO(jat): make use of the "rounding" attribute, currently only on CHF
      if ("DEFAULT".equalsIgnoreCase(curCode)) {
        defaultCurrencyFraction = digits; 
      } else {
        currencyFractions.put(curCode, digits);
      }
    }
    
    // find which currencies are still in use in some region, everything else
    // should be marked as deprecated
    iterator = supp.iterator(
        "//supplementalData/currencyData/region");
    while (iterator.hasNext()) {
      String path = iterator.next();
      parts.set(supp.getFullXPath(path));
      Map<String, String> attr = parts.findAttributes("currency");
      if (attr == null) {
        continue;
      }
      String region = parts.findAttributeValue("region", "iso3166");
      String curCode = attr.get("iso4217");
      if ("ZZ".equals(region) || "false".equals(attr.get("tender"))
          || "XXX".equals(curCode)) {
        // ZZ is an undefined region, XXX is an unknown currency code (and needs
        // to be special-cased because it is listed as used in Anartica!)
        continue;
      }
      String to = attr.get("to");
      if (to == null) {
        stillInUse.add(curCode);
      }
    }
  }
}
