/*
 * Copyright 2008 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.i18n.rebind;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameter;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.i18n.client.PluralRule;
import com.google.gwt.i18n.client.Messages.Optional;
import com.google.gwt.i18n.client.Messages.PluralCount;
import com.google.gwt.i18n.client.Messages.PluralText;
import com.google.gwt.i18n.client.PluralRule.PluralForm;
import com.google.gwt.i18n.client.impl.plurals.DefaultRule;
import com.google.gwt.i18n.rebind.AbstractResource.ResourceList;
import com.google.gwt.i18n.rebind.MessageFormatParser.ArgumentChunk;
import com.google.gwt.i18n.rebind.MessageFormatParser.TemplateChunk;
import com.google.gwt.i18n.shared.GwtLocale;
import com.google.gwt.user.rebind.AbstractGeneratorClassCreator;
import com.google.gwt.user.rebind.AbstractMethodCreator;

import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;

/**
 * Creator for methods of the form String getX(arg0,...,argN).
 */
class MessagesMethodCreator extends AbstractMethodCreator {

  /**
   * Implements {x,date...} references in MessageFormat.
   */
  private static class DateFormatter implements ValueFormatter {
    public String format(StringGenerator out, String subformat, String argName,
        JType argType) {
      if (!"java.util.Date".equals(argType.getQualifiedSourceName())) {
        return "Only java.util.Date acceptable for date format";
      }
      if (subformat == null || "medium".equals(subformat)) {
        out.appendExpression(dtFormatClassName + ".getMediumDateFormat()"
            + ".format(" + argName + ")", true);
      } else if ("full".equals(subformat)) {
        out.appendExpression(dtFormatClassName + ".getFullDateFormat().format("
            + argName + ")", true);
      } else if ("long".equals(subformat)) {
        out.appendExpression(dtFormatClassName + ".getLongDateFormat().format("
            + argName + ")", true);
      } else if ("short".equals(subformat)) {
        out.appendExpression(dtFormatClassName + ".getShortDateFormat()"
            + ".format(" + argName + ")", true);
      } else {
        out.appendExpression(dtFormatClassName + ".getFormat("
            + wrap(subformat) + ").format(" + argName + ")", true);
      }
      return null;
    }
  }

  /**
   * Implements {x,number...} references in MessageFormat.
   */
  private static class NumberFormatter implements ValueFormatter {
    public String format(StringGenerator out, String subformat, String argName,
        JType argType) {
      JPrimitiveType argPrimType = argType.isPrimitive();
      if (argPrimType == null || argPrimType == JPrimitiveType.BOOLEAN
          || argPrimType == JPrimitiveType.VOID) {
        return "Illegal argument type for number format";
      }
      if (subformat == null) {
        out.appendExpression(numFormatClassName + ".getDecimalFormat().format("
            + argName + ")", true);
      } else if ("integer".equals(subformat)) {
        out.appendExpression(numFormatClassName + ".getIntegerFormat().format("
            + argName + ")", true);
      } else if ("currency".equals(subformat)) {
        out.appendExpression(numFormatClassName
            + ".getCurrencyFormat().format(" + argName + ")", true);
      } else if ("percent".equals(subformat)) {
        out.appendExpression(numFormatClassName + ".getPercentFormat().format("
            + argName + ")", true);
      } else {
        out.appendExpression(numFormatClassName + ".getFormat("
            + wrap(subformat) + ").format(" + argName + ")", true);
      }
      return null;
    }
  }

  /**
   * Helper class to produce string expressions consisting of literals and
   * computed values.
   */
  private static class StringGenerator {

    /**
     * Output string buffer.
     */
    private StringBuffer buf;

    /**
     * True if we are in the middle of a string literal.
     */
    private boolean inString;

    /**
     * True if we have produced any output.
     */
    private boolean producedOutput;

    /**
     * Initialize the StringGenerator with an output buffer.
     * 
     * @param buf output buffer
     */
    public StringGenerator(StringBuffer buf) {
      this.buf = buf;
      producedOutput = false;
      inString = false;
    }

    /**
     * Append an expression to this string expression.
     * 
     * @param expression to add
     */
    public void appendExpression(String expression) {
      appendExpression(expression, false);
    }

    /**
     * Append an expression to this string expression.
     * 
     * @param expression to add
     * @param knownToBeString true if the expression is known to be of string
     *          type; otherwise ""+ will be prepended to ensure it.
     */
    public void appendExpression(String expression, boolean knownToBeString) {
      if (inString) {
        buf.append('"');
        inString = false;
        producedOutput = true;
      }
      if (producedOutput) {
        buf.append(" + ");
      } else if (!knownToBeString) {
        buf.append("\"\" + ");
      }
      buf.append(expression);
      producedOutput = true;
    }

    /**
     * Append part of a string literal.
     * 
     * @param ch part of string literal
     */
    public void appendStringLiteral(char ch) {
      if (!inString) {
        if (producedOutput) {
          buf.append(" + ");
        } else {
          producedOutput = true;
        }
        buf.append('"');
        inString = true;
      }
      buf.append(ch);
    }

    /**
     * Append part of a string literal.
     * 
     * @param str part of string literal
     */
    public void appendStringLiteral(String str) {
      if (!inString) {
        if (producedOutput) {
          buf.append(" + ");
        } else {
          producedOutput = true;
        }
        buf.append('"');
        inString = true;
      }
      buf.append(str);
    }

    /**
     * Complete the string, closing an open quote and handling empty strings.
     */
    public void completeString() {
      if (inString) {
        buf.append('\"');
      } else if (!producedOutput) {
        buf.append("\"\"");
      }
    }
  }

  /**
   * Implements {x,time...} references in MessageFormat.
   */
  private static class TimeFormatter implements ValueFormatter {
    public String format(StringGenerator out, String subformat, String argName,
        JType argType) {
      if (!"java.util.Date".equals(argType.getQualifiedSourceName())) {
        return "Only java.util.Date acceptable for date format";
      }
      if (subformat == null || "medium".equals(subformat)) {
        out.appendExpression(dtFormatClassName
            + ".getMediumTimeFormat().format(" + argName + ")", true);
      } else if ("full".equals(subformat)) {
        out.appendExpression(dtFormatClassName + ".getFullTimeFormat().format("
            + argName + ")", true);
      } else if ("long".equals(subformat)) {
        out.appendExpression(dtFormatClassName + ".getLongTimeFormat().format("
            + argName + ")", true);
      } else if ("short".equals(subformat)) {
        out.appendExpression(dtFormatClassName
            + ".getShortTimeFormat().format(" + argName + ")", true);
      } else {
        out.appendExpression(dtFormatClassName + ".getFormat("
            + wrap(subformat) + ").format(" + argName + ")", true);
      }
      return null;
    }
  }

  private interface ValueFormatter {
    /**
     * Creates code to format a value according to a format string.
     * 
     * @param out StringBuffer to append to
     * @param subformat the remainder of the format string
     * @param argName the name of the argument to use in the generated code
     * @param argType the type of the argument
     * @return null if no error or an appropriate error message
     */
    String format(StringGenerator out, String subformat, String argName,
        JType argType);
  }

  /**
   * Class names, in a refactor-friendly manner.
   */
  private static final String dtFormatClassName = DateTimeFormat.class.getCanonicalName();

  /**
   * Map of supported formats.
   */
  private static Map<String, ValueFormatter> formatters = new HashMap<String, ValueFormatter>();

  private static final String numFormatClassName = NumberFormat.class.getCanonicalName();

  /*
   * Register supported formats.
   */
  static {
    formatters.put("date", new DateFormatter());
    formatters.put("number", new NumberFormatter());
    formatters.put("time", new TimeFormatter());
    // TODO: implement ChoiceFormat and PluralFormat
  }

  /**
   * Constructor for <code>MessagesMethodCreator</code>.
   * 
   * @param classCreator associated class creator
   */
  public MessagesMethodCreator(AbstractGeneratorClassCreator classCreator) {
    super(classCreator);
  }

  @Override
  public void createMethodFor(TreeLogger logger, JMethod m, String key,
      ResourceList resourceList, GwtLocale locale)
      throws UnableToCompleteException {
    JParameter[] params = m.getParameters();
    int pluralParamIndex = -1;
    Class<? extends PluralRule> ruleClass = null;
    int numParams = params.length;
    boolean[] seenFlags = new boolean[numParams];

    // See if any parameter is tagged as a PluralCount parameter.
    for (int i = 0; i < numParams; ++i) {
      PluralCount pluralCount = params[i].getAnnotation(PluralCount.class);
      if (pluralCount != null) {
        if (pluralParamIndex >= 0) {
          throw error(logger, m.getName()
              + ": there can only be one PluralCount parameter");
        }
        JPrimitiveType primType = params[i].getType().isPrimitive();
        if (primType != JPrimitiveType.INT && primType != JPrimitiveType.SHORT) {
          throw error(logger, m.getName()
              + ": PluralCount parameter must be int or short");
        }
        pluralParamIndex = i;
        ruleClass = pluralCount.value();
      }
    }

    StringBuffer generated = new StringBuffer();
    if (ruleClass == null) {
      if (m.getAnnotation(PluralText.class) != null) {
        logger.log(TreeLogger.WARN, "Unused @PluralText on "
            + m.getEnclosingType().getSimpleSourceName() + "." + m.getName()
            + "; did you intend to mark a @PluralCount parameter?", null);
      }
    } else {
      if (ruleClass == PluralRule.class) {
        ruleClass = DefaultRule.class;
      }
      PluralRule rule = createLocalizedPluralRule(logger,
          m.getEnclosingType().getOracle(), ruleClass, locale);
      logger.log(TreeLogger.TRACE, "Using plural rule " + rule.getClass()
          + " for locale '" + locale + "'", null);
      generated.append(PluralRule.class.getCanonicalName());
      generated.append(" rule = new " + rule.getClass().getCanonicalName()
          + "();\n");
      generated.append("switch (rule.select("
          + params[pluralParamIndex].getName() + ")) {\n");
      PluralForm[] pluralForms = rule.pluralForms();
      resourceList.setPluralForms(key, pluralForms);
      // Skip default plural form (index 0); the fall-through case will handle
      // it.
      for (int i = 1; i < pluralForms.length; ++i) {
        String template = resourceList.getStringExt(key,
            pluralForms[i].getName());
        if (template != null) {
          generated.append("  // " + pluralForms[i].getName() + " - "
              + pluralForms[i].getDescription() + "\n");
          generated.append("  case " + i + ": return ");
          generateString(logger, template, params, seenFlags, generated);
          generated.append(";\n");
        } else if (pluralForms[i].getWarnIfMissing()) {
          logger.log(TreeLogger.WARN, "No plural form '"
              + pluralForms[i].getName() + "' defined for method '"
              + m.getName() + "' in " + m.getEnclosingType() + " for locale "
              + locale, null);
        }
      }
      generated.append("}\n");
    }
    generated.append("return ");
    String template = resourceList.getRequiredStringExt(key, null);
    generateString(logger, template, params, seenFlags, generated);

    // Generate an error if any required parameter was not used somewhere.
    for (int i = 0; i < numParams; ++i) {
      if (!seenFlags[i]) {
        Optional optional = params[i].getAnnotation(Optional.class);
        if (optional == null) {
          throw error(logger, "Required argument " + params[i].getName()
              + " not present: " + template);
        }
      }
    }

    generated.append(';');
    println(generated.toString());
  }

  /**
   * Creates an instance of a locale-specific plural rule implementation.
   * 
   * Note that this uses TypeOracle's ability to find all subclasses of the
   * supplied parent class, then uses reflection to actually load the class.
   * This works because PluralRule instances are required to be translatable,
   * since part of them is executed at runtime and part at compile time.
   * 
   * @param logger TreeLogger instance
   * @param oracle TypeOracle instance to use
   * @param ruleClass PluralRule implementation to localize
   * @param locale current locale we are compiling for
   * @return an instance of a PluralRule implementation. If an appropriate
   *         implementation of the requested class cannot be found, an instance
   *         of DefaultRule is used instead as a default of last resort.
   * @throws UnableToCompleteException if findDerivedClasses fails
   * 
   * TODO: consider impact of possibly having multiple TypeOracles
   */
  private PluralRule createLocalizedPluralRule(TreeLogger logger,
      TypeOracle oracle, Class<? extends PluralRule> ruleClass,
      GwtLocale locale)
      throws UnableToCompleteException {
    String baseName = ruleClass.getCanonicalName();
    JClassType ruleJClassType = oracle.findType(baseName);
    Map<String, JClassType> matchingClasses = LocalizableLinkageCreator.findDerivedClasses(
        logger, ruleJClassType);
    for (GwtLocale search : locale.getCompleteSearchList()) {
      JClassType localizedType = matchingClasses.get(search.toString());
      if (localizedType != null) {
        try {
          Class<?> testClass = Class.forName(
              localizedType.getQualifiedBinaryName(), false,
              PluralRule.class.getClassLoader());
          if (PluralRule.class.isAssignableFrom(testClass)) {
            return (PluralRule) testClass.newInstance();
          }
        } catch (ClassCastException e) {
          // ignore classes of the wrong type
        } catch (ClassNotFoundException e) {
          // ignore missing classes
        } catch (InstantiationException e) {
          // skip classes we can't instantiate
        } catch (IllegalAccessException e) {
          // ignore inaccessible classes
        }
      }
    }
    // default of last resort
    return new DefaultRule();
  }

  /**
   * Generate a Java string for a given MessageFormat string.
   * 
   * @param logger
   * @param template
   * @param params
   * @param seenFlag
   * @param outputBuf
   * @throws UnableToCompleteException
   */
  @SuppressWarnings("fallthrough")
  private void generateString(TreeLogger logger, String template,
      JParameter[] params, boolean[] seenFlag, StringBuffer outputBuf)
      throws UnableToCompleteException {
    StringGenerator buf = new StringGenerator(outputBuf);
    try {
      for (TemplateChunk chunk : MessageFormatParser.parse(template)) {
        if (chunk.isLiteral()) {
          buf.appendStringLiteral(chunk.getString());
        } else if (chunk instanceof ArgumentChunk) {
          ArgumentChunk argChunk = (ArgumentChunk) chunk;
          int argNumber = argChunk.getArgumentNumber();
          if (argNumber >= params.length) {
            throw error(logger, "Argument " + argNumber
                + " beyond range of arguments: " + template);
          }
          seenFlag[argNumber] = true;
          String arg = params[argNumber].getName();
          String format = argChunk.getFormat();
          if (format != null) {
            String subformat = argChunk.getSubFormat();
            ValueFormatter formatter = formatters.get(format);
            if (formatter != null) {
              String err = formatter.format(buf, subformat, arg,
                  params[argNumber].getType());
              if (err != null) {
                throw error(logger, err);
              }
              continue;
            }
          }
          // no format specified or unknown format
          // have to ensure that the result is stringified if necessary
          buf.appendExpression(
              arg,
              "java.lang.String".equals(params[argNumber].getType().getQualifiedSourceName()));
        } else {
          throw error(logger, "Unexpected result from parsing template "
              + template);
        }
      }
    } catch (ParseException e) {
      throw error(logger, e);
    }
    buf.completeString();
  }
}
