/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.myfaces.trinidadbuild.plugin.i18n.uixtools;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Enumeration;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

/**
 * Generates JavaScript libraries containing the Locale information from
 * Java.
 * @version $Name:  $ ($Revision: 1.3 $) $Date: 2004/03/25 22:36:42 $
 */
public class JSLocaleElementsGenerator
{
  public static void main(String[] args)
  {

    if ((args.length == 1) && ("?".equals(args[0])))
    {
      System.out.println("Generates JavaScript Locale information files");
      System.out.println("for the Locales available in the JVM.");
      System.out.println("These files are used by the Cabo HTML client");
      System.out.println("logic to handle date formatting and validation.");
      System.out.println();
      System.out.println("Parameters:");
      System.out.println("\tprettyPrint=false\tTurns off pretty printed output");
      System.out.println("\toutDir=[path]\t\tDirectory path to write JavaScript files to");
      System.out.println("\tsourceDir=[path]\t\tRoot directory path to write Java source to");
      System.out.println("\tbundleOutDir=[path]\t\tRoot directory path to write Java ResourceBundles to (defaults to sourceDir).");
      System.out.println("\tvariant=[variant name]\t\tIf supplied utility will generate ResourceBundles for this variant, and nothing else.");
      System.out.println("\tverbose=true\t\tTurns on verbose output");
      System.out.println("\tgenerateBundleBaseOnly=true\t\tGenerates the base LocaleElement.java file only");
      System.exit(0);
    }

    // whether the output should be pretty printed for legibility
    boolean prettyPrint = getArgBooleanValue(args, "prettyPrint", true);

    // whether verbose ouput should be generated.
    boolean verbose = getArgBooleanValue(args, "verbose", false);

    boolean writeSource = getArgBooleanValue(args, "writeSource", true);
    boolean writeJavascript = getArgBooleanValue(args, "writeJavascript", true);

    // whether only the Base LocaleElements.java file should be created.
    // this is based on the Locale.US
    boolean generateBundleBaseOnly = getArgBooleanValue(args,"generateBundleBaseOnly",false);

    // the output directory
    String outDir = getArgStringValue(args, "outDir", null);

    if (outDir == null)
    {
      outDir = System.getProperty("user.dir") +
               File.separator +
               _DEFAULT_LOCATION_PATH;
    }

    if (!outDir.endsWith(File.separator))
    {
      outDir = outDir + File.separator;
    }


    // the requested variant
    String variant = getArgStringValue(args, "variant", null);
    boolean writeAll = true;
    if (variant != null)
    {
      writeAll = false;
      variant = variant.toUpperCase();
    }

    // the source directory
    String sourceDir = getArgStringValue(args, "sourceDir", null);

    if (sourceDir == null)
    {
      sourceDir = System.getProperty("user.dir");
    }

    String bundleOutDir = getArgStringValue(args, "bundleOutDir", null);

    if (bundleOutDir == null)
      bundleOutDir = sourceDir;

    // The bundle output dir is the base of the heirarchy, we'll actually put
    // the files into the appropriate sub directory for the package.
    String fullBundleOutDir = (bundleOutDir
                               + (bundleOutDir.endsWith(File.separator)
                                  ? ""
                                  : File.separator)
                              + _DEFAULT_BUNDLE_LOCATION_PATH);

    String version = getArgStringValue(args, "version", null);
    version = VersionUtils.normalizeVersionSuffix(version);

    if (verbose)
    {
      System.out.println("Writing files to: " + outDir);
      if (writeAll)
      {
        System.out.println("Writing source to: " + sourceDir);
      }
      System.out.println("Writing bundles to: " + fullBundleOutDir);
    }

    try
    {
      File localeListFile = null;

      if (writeSource)
        (new File(fullBundleOutDir)).mkdirs();

      if (writeJavascript)
        (new File(outDir)).mkdirs();

      if (writeAll && writeSource && !generateBundleBaseOnly)
      {
        localeListFile = new File(sourceDir, _LOCALE_LIST_PATH);
        localeListFile.getParentFile().mkdirs();
        localeListFile.createNewFile();
      }

      Locale[] locales = null;

      if (generateBundleBaseOnly)
      {
         locales = new Locale[1];
         locales[0] = Locale.US;
      }
      else
      {
        locales = Locale.getAvailableLocales();
      }

      //
      // loop through the available Locales, writing their contents out
      // as JavaScript libraries and/or ResourceBundles
      //
      for (int i = 0; i < locales.length; i++)
      {
        // write the JavaSCript library for this locale
        _generateJSLocaleElements(outDir, fullBundleOutDir, locales[i],
                                  variant, prettyPrint, verbose,
                                  writeJavascript, writeSource, generateBundleBaseOnly, version);
      }

      // And write out a listing of all the locales, but  not when we want to
      // just generate the base Resource file.
      if (writeAll && writeSource && !generateBundleBaseOnly)
      {
        Writer sourceWriter = new FileWriter(localeListFile);
        sourceWriter.write(_LOCALE_LIST_CODE_START);

        for (int i = 0; i < locales.length; i++)
        {
          sourceWriter.write("    new Locale(\"");
          sourceWriter.write(locales[i].getLanguage());
          sourceWriter.write("\",\"");
          sourceWriter.write(locales[i].getCountry());
          sourceWriter.write("\",\"");
          sourceWriter.write(locales[i].getVariant());
          sourceWriter.write("\"),\n");
        }
        sourceWriter.write(_LOCALE_LIST_CODE_END);
        sourceWriter.close();
      }
    }
    catch (IOException e)
    {
      System.err.println(e);
      e.printStackTrace();
    }

    if (verbose)
    {
      System.out.println("Done writing files");
    }
  }

  private static String getArgStringValue(
    String[] args,
    String   argName,
    String   defaultValue
    )
  {
    int argLength = argName.length();

    for (int i = 0; i < args.length; i++)
    {
      String currArg = args[i];

      if (currArg.startsWith(argName))
      {
        if (!currArg.equals(argName) &&
            ('=' == currArg.charAt(argLength)))
        {
          return currArg.substring(argLength + 1);
        }
      }
    }

    return defaultValue;
  }

  private static boolean getArgBooleanValue(
    String[] args,
    String   argName,
    boolean  defaultValue
    )
  {
    //
    // check for = true or = false
    //
    String argValue = getArgStringValue(args, argName, null);

    if (argValue != null)
    {
      // check for = self
      if (argName.equals(argValue))
      {
        return true;
      }
      else
      {
        return Boolean.valueOf(argValue).booleanValue();
      }
    }

    //
    // check for the name by itself
    //
    for (int i = 0; i < args.length; i++)
    {
      if (args[i].equals(argName))
      {
        return true;
      }
    }

    //
    // check for the name turned off
    //
    String notName = "-" + argName;

    for (int i = 0; i < args.length; i++)
    {
      if (args[i].equals(notName))
      {
        return false;
      }
    }

    return defaultValue;
  }

  private static void _generateJSLocaleElements(
    String  outDir,
    String  bundleOutDir,
    Locale  targetLocale,
    String  variant,
    boolean prettyPrint,
    boolean verbose,
    boolean writeJavascript,
    boolean writeSource,
    boolean generateBundleBaseOnly,
    String version
    ) throws IOException
  {
    String fileName;
    PrintWriter localeWriter;

    if (variant == null && writeJavascript)
    {
      fileName = _getFileName(targetLocale, version, generateBundleBaseOnly) + _JAVASCRIPT_EXTENSION;

      if (verbose)
      {
        System.out.println("Writing " + fileName);
      }

      // create the file to write to
      localeWriter = new PrintWriter
        (new BufferedWriter(new FileWriter(outDir + fileName),
                            _DEFAULT_BUFFER_SIZE));
      _writeLocale(localeWriter, targetLocale, prettyPrint);
      localeWriter.close();
    }
  }

  private static void _writeJavaBundle(
    Writer      output,
    Locale      targetLocale,
    String      fileName
    ) throws IOException
  {
    output.write(_LOCALE_JAVA_CODE_START);
    output.write("public class "
                 + fileName
                 + " extends ListResourceBundle\n{\n"
                 + "  public Object[][] getContents()\n  {\n"
                 + "    return contents;\n  }\n\n");
    try
    {
      ResourceBundle elementsData =
        ResourceBundle.getBundle(_LOCALE_ELEMENTS_PATH, targetLocale);

      boolean doneOne = false;

      for (int i = 0; i < LOCALE_ELEMENTS_GET_KEYS.length; i ++)
      {
        String currKey = LOCALE_ELEMENTS_GET_KEYS[i];

        Object data = _getElementData(currKey, elementsData, targetLocale);
        _writeJavaBundleElement(output, currKey, data, doneOne);
        doneOne = true;
      }
      doneOne = false;
      output.write("  static final Object[][] contents = \n  {\n");
      for (int i = 0; i < LOCALE_ELEMENTS_GET_KEYS.length; i ++)
      {
        String currKey = LOCALE_ELEMENTS_GET_KEYS[i];
        output.write((doneOne ? ",\n" : "")
                     + "    { \""
                     + currKey
                     + "\", "
                     + _getKeyArrayName(currKey)
                     + "}");
        doneOne = true;
      }
      output.write("\n  };");
    }
    catch (MissingResourceException e)
    {
      // make sure that the class will, at least, compile even if incomplete.
      output.write("  // Bundle generation error:\n  // " + e);
      output.write("\n  static final Object[][] contents = null;");
      System.err.println(e);
    }
    output.write("\n}\n");
  }

  private static void _writeLocale(
    Writer      output,
    Locale      targetLocale,
    boolean     prettyPrint
    ) throws IOException
  {

    output.write("var LocaleSymbols_");
    output.write(targetLocale.toString());
    output.write(" = new LocaleSymbols({");

    if (prettyPrint)
      output.write('\n');


    // write the locale elements into the file
    _writeResourceContents(output,
                           _LOCALE_ELEMENTS_PATH,
                           new ArrayEnumeration(LOCALE_ELEMENTS_GET_KEYS),
                           targetLocale,
                           prettyPrint);

    output.write("});");

    if (prettyPrint)
      output.write('\n');
  }


  private static void _writeResourceContents(
    Writer      output,
    String      baseName,
    Enumeration keys,
    Locale      targetLocale,
    boolean     prettyPrint
    ) throws IOException
  {
    try
    {
      while(keys.hasMoreElements())
      {
        String currKey = (String)keys.nextElement();

        Object data = null;

        if ("CurrencyElements".equals(currKey))
          data = _getCurrencyData(targetLocale);
        else if ("PercentElements".equals(currKey))
          data = _getPercentData(targetLocale);
        else
          data = LocaleDataResolver.getElementData(currKey, targetLocale);

        boolean wroteElement = _writeResourceElement(
                                    output,
                                    currKey,
                                    data,
                                    keys.hasMoreElements(),
                                    prettyPrint);

        if (wroteElement && prettyPrint)
        {
          output.write('\n');
        }
      }
    }
    catch (MissingResourceException e)
    {
      System.err.println(e);
    }
  }

  private static Object _getCurrencyData(
    Locale targetLocale)
  {
    DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(targetLocale);
    DecimalFormatSymbols decimalFormatSymbols = df.getDecimalFormatSymbols();
    Object[] currencyData = new Object[6];
    currencyData[0] = decimalFormatSymbols.getCurrencySymbol(); 
    currencyData[1] = decimalFormatSymbols.getCurrency().getCurrencyCode();
    currencyData[2] = df.getPositivePrefix();
    currencyData[3] = df.getPositiveSuffix();
    currencyData[4] = df.getNegativePrefix();
    currencyData[5] = df.getNegativeSuffix();

    return currencyData;
  }
  
  private static Object _getPercentData(
    Locale targetLocale)
  {
    DecimalFormat df = (DecimalFormat)NumberFormat.getPercentInstance(targetLocale);
    Object[] percentData = new Object[2];
    percentData[0] = df.getPositiveSuffix();
    percentData[1] = df.getNegativeSuffix();
    //percentData[2] = df.getPositivePrefix();
    //percentData[3] = df.getNegativePrefix();  

    return percentData;
  }

  private static Object _getElementData(
    String currKey,
    ResourceBundle elementsData,
    Locale targetLocale
   )
  {
    return elementsData.getObject(currKey);
  }

  private static boolean _writeResourceElement(
    Writer  output,
    String  key,
    Object  value,
    boolean notLast,
    boolean prettyPrint
    ) throws IOException
  {
    if (key != null)
    {
      // start writing element, using key as the property name
      output.write(key);
      output.write(':');
    }

    Object[] values = null;
    int valueCount = 0;

    if (value instanceof Object[])
    {
      values = (Object[])value;

      valueCount = values.length;

      if (valueCount == 0)
      {
        value = "";
      }
    }

    if (valueCount != 0)
    {
      // output.write("new Array(");
      output.write('[');

      for (int i = 0; i < valueCount; i++)
      {
        _writeResourceElement(output,
                              null,
                              values[i],
                              i < valueCount - 1,
                              prettyPrint);
      }

      //output.write(')');
      output.write(']');
    }
    else
    {
      output.write('\"');
      _writeEscapedString(output, value.toString(), false);
      output.write('\"');
    }

    if (notLast)
    {
      output.write(',');

      if (prettyPrint)
      {
        output.write(' ');
      }
    }

    // we wrote some ouput
    return true;
  }

  private static void _writeJavaBundleElement(
    Writer  output,
    String  key,
    Object  value,
    boolean wasPrevious
    ) throws IOException
  {
    output.write("  private static final String "
                 + _getKeyArrayName(key)
                 + "[]");
    Object[] values = null;
    int valueCount = 0;
    boolean doneOne = false;

    if (value instanceof Object[])
    {
      values = (Object[]) value;

      valueCount = values.length;

      if (valueCount <= 0)
      {
        values = _EMPTY_VALUES;
        valueCount = 1;
      }
    }

    if (valueCount > 0)
    {
      output.write(" = \n  {\n");
      for (int i = 0; i < valueCount; i++)
      {
        output.write((doneOne ? ", \n" : "") + "    \"");
        _writeEscapedString(output, values[i].toString(), true);
        output.write("\"");
        doneOne = true;
      }
      output.write("\n  };\n\n");
    }
    else
      output.write(" = null");
  }

  private static void _writeEscapedString(
    Writer output,
    String value,
    boolean isJava
    ) throws IOException
  {
    int length = value.length();

    for (int i = 0; i < length; i++)
    {
      char currChar = value.charAt(i);

      if (currChar > 255)
      {
        output.write("\\u");
        output.write(_getHexString(currChar, 4));
      }
      else
      {
        if (isJava)
        {
          if ((currChar > 31)
              && (currChar < 128))
          {
            if (currChar == '\"')
              output.write("\\\"");
            else
              output.write(currChar);
          }
          else
          {
            output.write("\\u");
            output.write(_getHexString(currChar, 4));
          }
        }
        else
        {
          // write ascii printable characters, except for the double quote,
          // which needs to be escaped because we are already in a String.
          if ((currChar > 31)    &&
              (currChar < 128)   &&
              (currChar != '\"') &&
              (currChar != '\''))
          {
            output.write(currChar);
          }
          else
          {
            output.write("\\x");
            output.write(_getHexString(currChar, 2));
          }
        }
      }
    }
  }


  private static String _getHexString(
    int number,
    int minDigits
    )
  {
    String hexString = Integer.toHexString(number);

    int hexLength = hexString.length();

    int zeroPadding = minDigits - hexLength;

    if (zeroPadding > 0)
    {
      String paddedString = "0";

      while (zeroPadding > 1)
      {
        paddedString += "0";
        zeroPadding--;
      }

      hexString = paddedString + hexString;
    }
    else
    {
      if (zeroPadding < 0)
      {
        throw new IllegalArgumentException();
      }
    }

    return hexString;
  }

  private static String _getKeyArrayName(String key)
  {
    return "_array" + key;
  }

  private static String _getFileName(
    Locale locale,
    String version,
    boolean generateBundleBaseOnly
    )
  {

    if (generateBundleBaseOnly)
    {
      return "LocaleElements";
    }

    if (version == null)
      return "LocaleElements_" + locale;
    return "LocaleElements_" + locale + version;
  }

  private static String _getLocaleSuffix(
    Locale locale
    )
  {
    String localeString =  locale.toString();

    return localeString.substring(localeString.indexOf('_'));
  }

  //
  // Array of DateFormatZoneData key names to retrieve.
  // Only keys from this list are used to generate locale information
  //
  private static final String[] LOCALE_ELEMENTS_GET_KEYS = 
  {
    "MonthNames",
    "MonthAbbreviations",
    "DayNames",
    "DayAbbreviations",
    "AmPmMarkers",
    "Eras",
    "DateTimePatterns",
    "DateTimeElements",
    "NumberElements",
    "CurrencyElements",
    "PercentElements"
  };

  //
  // Array of DateFormatZoneData key names to retrieve.
  // Only keys from this list are used to generate locale information
  //
  private static final String[] LOCALE_ELEMENTS_MAPPINGS = 
  {
    "MonthNames", "getMonths",
    "MonthAbbreviations", "getShortMonths",
    "DayNames", "getWeekdays",
    "DayAbbreviations", "getShortWeekdays",
    "AmPmMarkers", "getAmPmStrings",
    "Eras", "getEras",
    "DateTimePatterns", null,
    "DateTimeElements", null,
    "NumberElements", null
  };

  //
  // Array of LocaleElements key names to retrieve.
  // Only keys from this list are used to generate locale information
  //
  private static final String[] DATE_FORMAT_ZONE_GET_KEYS = {};

  // J2SE 1.3:
  // private static String _RESOURCES_PACKAGE = "java.text.resources";

  // J2SE 1.4:
  private static String _RESOURCES_PACKAGE = "sun.text.resources";

  private static final String _DATE_FORMAT_ZONE_PATH =
                          _RESOURCES_PACKAGE + ".DateFormatZoneData";

  private static final String _LOCALE_ELEMENTS_PATH =
                          _RESOURCES_PACKAGE + ".LocaleElements";

  private static final String _DEFAULT_LOCATION_PATH =
          "org\\apache\\myfaces\\trinidadinternal\\ui\\jsLibs\\resources\\".replace('\\',
                                                          File.separatorChar);

  // Mimicking to be in api path. In the trinidad-faces impl side we have
  // the following directory structure. There is identical directory sturcture
  // in trinidad-faces api side.
  // Only _TRINIDAD_LOCALE_ELEMENT base file will be added to the api side,
  // while all the variants will be in impl side in the directory structure
  // defined below.
  private static final String _TRINIDAD_LOCALE_ELEMENTS_PACKAGE =
    "org.apache.myfaces.trinidad.resource";

  public static final String _DEFAULT_BUNDLE_LOCATION_PATH =
    (_TRINIDAD_LOCALE_ELEMENTS_PACKAGE.replace('.', File.separatorChar)
     + File.separatorChar);

  private static final String _TRINIDAD_LOCALE_ELEMENTS_PATH =
    _TRINIDAD_LOCALE_ELEMENTS_PACKAGE + ".LocaleElements";

  // buffer size of the BufferedWriter to which output is written
  private static final int _DEFAULT_BUFFER_SIZE = 1 << 14;

  private static final String _LOCALE_LIST_PATH =
          "org\\apache\\myfaces\\trinidadinternal\\ui\\laf\\base\\xhtml\\LocaleList.java".replace('\\',
                                                          File.separatorChar);

  private static final String _EMPTY_VALUES[] = { "" };

  private static final String _LOCALE_LIST_CODE_START =
"/*\n" +
"**\n" +
"**34567890123456789012345678901234567890123456789012345678901234567890123456789\n" +
"*/\n" +
"package org.apache.myfaces.trinidadinternal.ui.laf.base.xhtml;\n" +
"\n" +
"import java.util.Locale;\n" +
"\n" +
"import java.util.HashMap;\n" +
"\n" +
"/*\n" +
" * List of supported locales.  Automatically generated - do not modify!\n" +
" */\n" +
"public class LocaleList\n" +
"{\n" +
"  /*\n" +
"   * Returns the list of supported locales.\n" +
"   */\n" +
"  static public HashMap<Locale, Locale> getSupportedLocales()\n" +
"  {\n" +
"    return _sLocaleMapper;\n" +
"  }\n" +
"  \n" +
"  private LocaleList()\n" +
"  {\n" +
"  }\n" +
"\n" +
"  static private final Locale[] _sLocales = new Locale[]\n" +
"  {\n";


  private static final String _LOCALE_LIST_CODE_END =
"  };\n" +
"\n" +
"  static private HashMap<Locale, Locale> _sLocaleMapper;\n" +
"\n" +
"  static\n" +
"  {\n" +
"    _sLocaleMapper = new HashMap<Locale, Locale>();\n" +
"    for(Locale locale : _sLocales)\n" +
"    {\n" +
"      _sLocaleMapper.put(locale, locale);\n" +
"    }\n" +
"  }\n" +
"}\n";

  private static final String _LOCALE_JAVA_CODE_START =
    "// Do not edit this file!\n"
    + "// This file has been automatically generated.\n"
    + "// Edit JSLocaleElementsGenerator instead.\n//\n"
    + "package "
    + _TRINIDAD_LOCALE_ELEMENTS_PACKAGE
    + ";\n\n"
    + "import java.util.ListResourceBundle;\n";

  private static final String _JAVASCRIPT_EXTENSION = ".js";
  private static final String _JAVA_EXTENSION = ".java";
 
  //Introduced to remove the dependency on bali-share in the api side.
  private static class ArrayEnumeration implements Enumeration
  {
    public ArrayEnumeration(Object[] array)
    {
      _objects = (array == null)? _EMPTY_ARRAY : array;
    }

    public boolean hasMoreElements()
    {
      return _currentIndex < _objects.length;
    }

    public Object nextElement()
    {
      return _objects[_currentIndex++];
    }

    private Object[] _objects;

    private int _currentIndex;

    private static final Object[] _EMPTY_ARRAY = new Object[0];
  }
}
