/*
 * 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.Factory;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

/**
 * Base class for CLDR processors that generate GWT i18n resources.
 */
public abstract class Processor {

  protected static final String I18N_PACKAGE_PATH = "user/src/com/google/gwt/i18n/";

  protected static <T> String join(String joiner, Iterable<T> objects) {
    StringBuilder buf = new StringBuilder();
    for (Object obj : objects) {
      if (buf.length() > 0) {
        buf.append(joiner);
      }
      buf.append(obj.toString());
    }
    return buf.toString();
  }

  protected static String localeSuffix(GwtLocale locale) {
    return (locale.isDefault() ? "" : "_") + locale.getAsString();
  }
  
  /**
   * @param value
   * @return value with all quotes escaped
   */
  protected static String quote(String value) {
    return value.replace("\"", "\\\"");
  }

  protected final Factory cldrFactory;  

  protected final LocaleData localeData;

  protected final File outputDir;

  private boolean useOverride;

  /**
   * Initialize the shared portion of a Processor.
   * 
   * @param outputDir output directory for created files
   * @param cldrFactory CLDR factory used to create new CLDRFile instances
   * @param localeData LocaleData instance to collect data from CLDR files
   */
  protected Processor(File outputDir, Factory cldrFactory,
      LocaleData localeData) {
    this.outputDir = outputDir;
    this.cldrFactory = cldrFactory;
    this.localeData = localeData;
    useOverride = true;
  }

  /**
   * Execute this processor.
   * 
   * It will call loadData, cleanupData, writeOutputFiles, and then reset on
   * its localeData instance.
   *  
   * @throws IOException
   */
  public final void run() throws IOException {
    try {
      loadData();
      cleanupData();
      writeOutputFiles();
    } finally {
      localeData.reset();
    }
  }

  /**
   * Override hook for subclasses to implement any cleanup needed, such as
   * removing values which duplicate those from ancestors.
   */
  protected void cleanupData() {
    // do nothing by default
  }

  /**
   * Create an output file including any parent directories.
   * 
   * @param name name of file, which will be prefixed by
   *     user/src/com/google/gwt/i18n/client/impl/cldr
   * @param ext extension for file
   * @param locale locale name or null if not localized
   * @return a PrintWriter instance
   * @throws IOException
   */
  protected PrintWriter createFile(String name, String ext, String locale)
      throws IOException {
    if (locale == null || locale.length() == 0) {
      locale = "";
    } else {
      locale = "_" + locale;
    }
    return createOutputFile("client/impl/cldr/" + name + locale + "." + ext);
  }

  protected PrintWriter createOutputFile(String suffix)
      throws IOException, FileNotFoundException {
    return createOutputFile(I18N_PACKAGE_PATH, suffix);
  }

  protected PrintWriter createOutputFile(String prefix, String suffix)
      throws IOException, FileNotFoundException {
    PrintWriter pw;
    File f = new File(outputDir, prefix + suffix);
    File parent = f.getParentFile();
    if (parent != null) {
      parent.mkdirs();
    }
    f.createNewFile();
    pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
        new FileOutputStream(f), "UTF-8")), false);
    return pw;
  }

  protected void generateIntMethod(PrintWriter pw, String category,
      GwtLocale locale, String key, String method) {
    String value = localeData.getEntry(category, locale, key);
    if (value != null) {
      pw.println();
      if (useOverride) {
        pw.println("  @Override");
      }
      pw.println("  public int " + method + "() {");
      pw.println("    return " + value + ";");
      pw.println("  }");
    }
  }

  protected void generateStringMethod(PrintWriter pw, String category,
      GwtLocale locale, String key, String method) {
    String value = localeData.getEntry(category, locale, key);
    generateStringValue(pw, method, value);
  }

  protected void generateStringValue(PrintWriter pw, String method,
      String value) {
    if (value != null) {
      pw.println();
      if (useOverride) {
        pw.println("  @Override");
      }
      pw.println("  public String " + method + "() {");
      pw.println("    return \"" + quote(value) + "\";");
      pw.println("  }");
    }
  }

  /**
   * @return true if generated methods should use @Override.
   */
  protected boolean getOverrides() {
    return useOverride;
  }

  /**
   * Load data needed by this processor.
   *
   * @throws IOException
   */
  protected abstract void loadData() throws IOException;

  protected void printHeader(PrintWriter pw) {
    pw.println("/*");
    pw.println(" * Copyright 2010 Google Inc.");
    pw.println(" * ");
    pw.println(" * Licensed under the Apache License, Version 2.0 (the "
        + "\"License\"); you may not");
    pw.println(" * use this file except in compliance with the License. You "
        + "may obtain a copy of");
    pw.println(" * the License at");
    pw.println(" * ");
    pw.println(" * http://www.apache.org/licenses/LICENSE-2.0");
    pw.println(" * ");
    pw.println(" * Unless required by applicable law or agreed to in writing, "
        + "software");
    pw.println(" * distributed under the License is distributed on an \"AS "
        + "IS\" BASIS, WITHOUT");
    pw.println(" * WARRANTIES OR CONDITIONS OF ANY KIND, either express or "
        + "implied. See the");
    pw.println(" * License for the specific language governing permissions and "
        + "limitations under");
    pw.println(" * the License.");
    pw.println(" */");
  }

  /**
   * Set whether method definitions should use @Override.
   * 
   * @param useOverride
   */
  protected void setOverrides(boolean useOverride) {
    this.useOverride = useOverride;
  }

  /**
   * Write output files produced by this processor.
   *
   * @throws IOException
   */
  protected abstract void writeOutputFiles() throws IOException;
}
