/*
 * 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 static com.google.gwt.i18n.rebind.AnnotationUtil.getClassAnnotation;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.JArrayType;
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.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JRawType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.i18n.client.PluralRule;
import com.google.gwt.i18n.client.Constants.DefaultBooleanValue;
import com.google.gwt.i18n.client.Constants.DefaultDoubleValue;
import com.google.gwt.i18n.client.Constants.DefaultFloatValue;
import com.google.gwt.i18n.client.Constants.DefaultIntValue;
import com.google.gwt.i18n.client.Constants.DefaultStringArrayValue;
import com.google.gwt.i18n.client.Constants.DefaultStringMapValue;
import com.google.gwt.i18n.client.Constants.DefaultStringValue;
import com.google.gwt.i18n.client.LocalizableResource.DefaultLocale;
import com.google.gwt.i18n.client.LocalizableResource.Description;
import com.google.gwt.i18n.client.LocalizableResource.GenerateKeys;
import com.google.gwt.i18n.client.LocalizableResource.Key;
import com.google.gwt.i18n.client.LocalizableResource.Meaning;
import com.google.gwt.i18n.client.Messages.DefaultMessage;
import com.google.gwt.i18n.client.Messages.Example;
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.rebind.keygen.KeyGenerator;
import com.google.gwt.i18n.rebind.keygen.MethodNameKeyGenerator;
import com.google.gwt.i18n.shared.GwtLocale;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * AbstractResource implementation which looks up text annotations on classes.
 */
public class AnnotationsResource extends AbstractResource {

  /**
   * An exception indicating there was some problem with an annotation.
   * 
   * A caller receiving this exception should log the human-readable message and
   * treat it as a fatal error.
   */
  public static class AnnotationsError extends Exception {

    public AnnotationsError(String msg) {
      super(msg);
    }
  }

  /**
   * Class for argument information, used for export.
   */
  public static class ArgumentInfo {

    public String example;
    public boolean isPluralCount;
    public String name;
    public boolean optional;
    public Class<? extends PluralRule> pluralRuleClass;

    public ArgumentInfo(String name) {
      this.name = name;
    }
  }

  private static class EntryWrapper implements ResourceEntry {

    private final String key;
    private final MethodEntry entry;

    public EntryWrapper(String key, MethodEntry entry) {
      this.key = key;
      this.entry = entry;
    }

    public String getForm(String form) {
      return form == null ? entry.text : entry.pluralText.get(form);
    }

    public Collection<String> getForms() {
      return entry.pluralText.keySet();
    }

    public String getKey() {
      return key;
    }
  }

  /**
   * Class to keep annotation information about a particular method.
   */
  private static class MethodEntry {

    // Strings used in toString for formatting.
    private static final String DETAILS_PREFIX = " (";
    private static final String DETAILS_SEPARATOR = ", ";

    public ArrayList<ArgumentInfo> arguments;
    public String description;
    public String meaning;
    public Map<String, String> pluralText;
    public String text;

    public MethodEntry(String text, String meaning) {
      this.text = text;
      this.meaning = meaning;
      pluralText = new HashMap<String, String>();
      arguments = new ArrayList<ArgumentInfo>();
    }

    public ArgumentInfo addArgument(String argName) {
      ArgumentInfo argInfo = new ArgumentInfo(argName);
      arguments.add(argInfo);
      return argInfo;
    }

    public void addPluralText(String form, String pluralFormText) {
      pluralText.put(form, pluralFormText);
    }

    @Override
    public String toString() {
      StringBuilder buf = new StringBuilder();
      buf.append(text);
      String prefix = DETAILS_PREFIX;
      if (meaning != null) {
        buf.append(prefix).append("meaning=").append(meaning);
        prefix = DETAILS_SEPARATOR;
      }
      if (description != null) {
        buf.append(prefix).append("desc=").append(description);
        prefix = DETAILS_SEPARATOR;
      }
      if (DETAILS_SEPARATOR == prefix) {
        buf.append(')');
      }
      return buf.toString();
    }
  }

  /**
   * Returns the key for a given method.
   *
   * If null is returned, an error message has already been logged.
   *
   * @param logger 
   * @param keyGenerator 
   * @param method 
   * @param isConstants 
   * @return null if unable to get or compute the key for this method, otherwise
   *         the key is returned
   */
  public static String getKey(TreeLogger logger, KeyGenerator keyGenerator,
      JMethod method, boolean isConstants) {
    Key key = method.getAnnotation(Key.class);
    if (key != null) {
      return key.value();
    }
    String text;
    try {
      text = getTextString(method, null, isConstants);
    } catch (AnnotationsError e) {
      return null;
    }
    String meaningString = null;
    Meaning meaning = method.getAnnotation(Meaning.class);
    if (meaning != null) {
      meaningString = meaning.value();
    }
    if (keyGenerator == null) {
      // Gracefully handle the case of an invalid KeyGenerator classname
      return null;
    }
    String keyStr = keyGenerator.generateKey(
        method.getEnclosingType().getQualifiedSourceName(), method.getName(),
        text, meaningString);
    if (keyStr == null) {
      if (text == null) {
        logger.log(
            TreeLogger.ERROR,
            "Key generator "
                + keyGenerator.getClass().getName()
                + " requires the default value be specified in an annotation for method "
                + method.getName(), null);
      } else {
        logger.log(TreeLogger.ERROR, "Key generator "
            + keyGenerator.getClass().getName()
            + " was unable to compute a key value for method "
            + method.getName(), null);
      }
    }
    return keyStr;
  }

  /**
   * Returns a suitable key generator for the specified class.
   * 
   * @param targetClass 
   * @return KeyGenerator instance, guaranteed to not be null 
   * @throws AnnotationsError if a specified KeyGenerator cannot be created
   */
  public static KeyGenerator getKeyGenerator(JClassType targetClass)
      throws AnnotationsError {
    GenerateKeys generator = getClassAnnotation(targetClass, GenerateKeys.class);
    if (generator != null) {
      String className = generator.value();
      try {
        Class<? extends KeyGenerator> keyGeneratorClass = Class.forName(
            className, false, KeyGenerator.class.getClassLoader()).asSubclass(
            KeyGenerator.class);
        return keyGeneratorClass.newInstance();
      } catch (InstantiationException e) {
        throw new AnnotationsError("@GenerateKeys: unable to instantiate "
            + className);
      } catch (IllegalAccessException e) {
        throw new AnnotationsError("@GenerateKeys: unable to instantiate "
            + className);
      } catch (ClassNotFoundException e) {
        throw new AnnotationsError("Invalid class specified to @GenerateKeys: "
            + className);
      }
    }
    return new MethodNameKeyGenerator();
  }

  /**
   * Return the text string from annotations for a particular method.
   * 
   * @param method the method to retrieve text
   * @param map if not null, add keys for DefaultStringMapValue to this map
   * @param isConstants true if the method is in a subinterface of Constants
   * @throws AnnotationsError if the annotation usage is incorrect
   * @return the text value to use for this method, as if read from a properties
   *         file, or null if there are no annotations.
   */
  private static String getTextString(JMethod method,
      Map<String, MethodEntry> map, boolean isConstants)
      throws AnnotationsError {
    JType returnType = method.getReturnType();
    DefaultMessage defaultText = method.getAnnotation(DefaultMessage.class);
    DefaultStringValue stringValue = method.getAnnotation(DefaultStringValue.class);
    DefaultStringArrayValue stringArrayValue = method.getAnnotation(DefaultStringArrayValue.class);
    DefaultStringMapValue stringMapValue = method.getAnnotation(DefaultStringMapValue.class);
    DefaultIntValue intValue = method.getAnnotation(DefaultIntValue.class);
    DefaultFloatValue floatValue = method.getAnnotation(DefaultFloatValue.class);
    DefaultDoubleValue doubleValue = method.getAnnotation(DefaultDoubleValue.class);
    DefaultBooleanValue booleanValue = method.getAnnotation(DefaultBooleanValue.class);
    int constantsCount = 0;
    if (stringValue != null) {
      constantsCount++;
      if (!returnType.getQualifiedSourceName().equals("java.lang.String")) {
        throw new AnnotationsError(
            "@DefaultStringValue can only be used with a method returning String");
      }
    }
    if (stringArrayValue != null) {
      constantsCount++;
      JArrayType arrayType = returnType.isArray();
      if (arrayType == null
          || !arrayType.getComponentType().getQualifiedSourceName().equals(
              "java.lang.String")) {
        throw new AnnotationsError(
            "@DefaultStringArrayValue can only be used with a method returning String[]");
      }
    }
    if (stringMapValue != null) {
      constantsCount++;
      JRawType rawType = returnType.getErasedType().isRawType();
      boolean error = false;
      if (rawType == null
          || !rawType.getQualifiedSourceName().equals("java.util.Map")) {
        error = true;
      } else {
        JParameterizedType paramType = returnType.isParameterized();
        if (paramType != null) {
          JType[] args = paramType.getTypeArgs();
          if (args.length != 2
              || !args[0].getQualifiedSourceName().equals("java.lang.String")
              || !args[1].getQualifiedSourceName().equals("java.lang.String")) {
            error = true;
          }
        }
      }
      if (error) {
        throw new AnnotationsError(
            "@DefaultStringMapValue can only be used with a method "
                + "returning Map or Map<String,String>");
      }
    }
    if (intValue != null) {
      constantsCount++;
      JPrimitiveType primType = returnType.isPrimitive();
      if (primType != JPrimitiveType.INT) {
        throw new AnnotationsError(
            "@DefaultIntValue can only be used with a method returning int");
      }
    }
    if (floatValue != null) {
      constantsCount++;
      JPrimitiveType primType = returnType.isPrimitive();
      if (primType != JPrimitiveType.FLOAT) {
        throw new AnnotationsError(
            "@DefaultFloatValue can only be used with a method returning float");
      }
    }
    if (doubleValue != null) {
      constantsCount++;
      JPrimitiveType primType = returnType.isPrimitive();
      if (primType != JPrimitiveType.DOUBLE) {
        throw new AnnotationsError(
            "@DefaultDoubleValue can only be used with a method returning double");
      }
    }
    if (booleanValue != null) {
      constantsCount++;
      JPrimitiveType primType = returnType.isPrimitive();
      if (primType != JPrimitiveType.BOOLEAN) {
        throw new AnnotationsError(
            "@DefaultBooleanValue can only be used with a method returning boolean");
      }
    }
    if (!isConstants) {
      if (constantsCount > 0) {
        throw new AnnotationsError(
            "@Default*Value is not permitted on a Messages interface; see @DefaultText");
      }
      if (defaultText != null) {
        return defaultText.value();
      }
    } else {
      if (defaultText != null) {
        throw new AnnotationsError(
            "@DefaultText is not permitted on a Constants interface; see @Default*Value");
      }
      if (constantsCount > 1) {
        throw new AnnotationsError(
            "No more than one @Default*Value annotation may be used on a method");
      }
      if (stringValue != null) {
        return stringValue.value();
      } else if (intValue != null) {
        return Integer.toString(intValue.value());
      } else if (floatValue != null) {
        return Float.toString(floatValue.value());
      } else if (doubleValue != null) {
        return Double.toString(doubleValue.value());
      } else if (booleanValue != null) {
        return Boolean.toString(booleanValue.value());
      } else if (stringArrayValue != null) {
        StringBuilder buf = new StringBuilder();
        boolean firstString = true;
        for (String str : stringArrayValue.value()) {
          str = str.replace("\\", "\\\\");
          str = str.replace(",", "\\,");
          if (!firstString) {
            buf.append(',');
          } else {
            firstString = false;
          }
          buf.append(str);
        }
        return buf.toString();
      } else if (stringMapValue != null) {
        StringBuilder buf = new StringBuilder();
        boolean firstString = true;
        String[] entries = stringMapValue.value();
        if ((entries.length & 1) != 0) {
          throw new AnnotationsError(
              "Odd number of strings supplied to @DefaultStringMapValue");
        }
        for (int i = 0; i < entries.length; i += 2) {
          String key = entries[i];
          String value = entries[i + 1];

          if (map != null) {
            // add key=value part to map
            MethodEntry entry = new MethodEntry(value, null);
            map.put(key, entry);
          }

          // add the key to the master entry
          key = key.replace("\\", "\\\\");
          key = key.replace(",", "\\,");
          if (!firstString) {
            buf.append(',');
          } else {
            firstString = false;
          }
          buf.append(key);
        }
        return buf.toString();
      }
    }
    return null;
  }

  private Map<String, MethodEntry> map;

  /**
   * Create a resource that supplies data from i18n-related annotations.
   * 
   * @param logger
   * @param clazz
   * @param locale
   * @param isConstants
   * @throws AnnotationsError if there is a fatal error while processing
   *           annotations
   */
  public AnnotationsResource(TreeLogger logger, JClassType clazz,
      GwtLocale locale, boolean isConstants) throws AnnotationsError {
    super(locale);
    KeyGenerator keyGenerator = getKeyGenerator(clazz);
    map = new HashMap<String, MethodEntry>();
    setPath(clazz.getQualifiedSourceName());
    String defLocaleValue = null;
    
    // If the class has an embedded locale in it, use that for the default
    String className = clazz.getSimpleSourceName();
    int underscore = className.indexOf('_');
    if (underscore >= 0) {
      defLocaleValue = className.substring(underscore + 1);
    }
    
    // If there is an annotation declaring the default locale, use that
    DefaultLocale defLocaleAnnot = getClassAnnotation(clazz,
        DefaultLocale.class);
    if (defLocaleAnnot != null) {
      defLocaleValue = defLocaleAnnot.value();
    }
    GwtLocale defLocale = LocaleUtils.getLocaleFactory().fromString(
        defLocaleValue);
    if (!locale.isDefault() && !locale.equals(defLocale)) {
      logger.log(TreeLogger.WARN, "Default locale " + defLocale + " on "
          + clazz.getQualifiedSourceName() + " doesn't match " + locale);
      return;
    }
    matchLocale = defLocale;
    for (JMethod method : clazz.getMethods()) {
      String meaningString = null;
      Meaning meaning = method.getAnnotation(Meaning.class);
      if (meaning != null) {
        meaningString = meaning.value();
      }
      String textString = getTextString(method, map, isConstants);
      if (textString == null) {
        // ignore ones without some value annotation
        continue;
      }
      String key = null;
      Key keyAnnot = method.getAnnotation(Key.class);
      if (keyAnnot != null) {
        key = keyAnnot.value();
      } else {
        key = keyGenerator.generateKey(
            method.getEnclosingType().getQualifiedSourceName(),
            method.getName(), textString, meaningString);
      }
      if (key == null) {
        throw new AnnotationsError("Could not compute key for "
            + method.getEnclosingType().getQualifiedSourceName() + "."
            + method.getName());
      }
      MethodEntry entry = new MethodEntry(textString, meaningString);
      map.put(key, entry);
      Description description = method.getAnnotation(Description.class);
      if (description != null) {
        entry.description = description.value();
      }
      PluralText pluralText = method.getAnnotation(PluralText.class);
      if (pluralText != null) {
        String[] pluralForms = pluralText.value();
        if ((pluralForms.length & 1) != 0) {
          throw new AnnotationsError(
              "Odd number of strings supplied to @PluralText: must be"
              + " pairs of form names and strings");
        }
        for (int i = 0; i + 1 < pluralForms.length; i += 2) {
          entry.addPluralText(pluralForms[i], pluralForms[i + 1]);
        }
      }
      for (JParameter param : method.getParameters()) {
        ArgumentInfo argInfo = entry.addArgument(param.getName());
        Optional optional = param.getAnnotation(Optional.class);
        if (optional != null) {
          argInfo.optional = true;
        }
        PluralCount pluralCount = param.getAnnotation(PluralCount.class);
        if (pluralCount != null) {
          argInfo.isPluralCount = true;
        }
        Example example = param.getAnnotation(Example.class);
        if (example != null) {
          argInfo.example = example.value();
        }
      }
    }
  }

  @Override
  public void addToKeySet(Set<String> s) {
    s.addAll(map.keySet());
  }

  public Iterable<ArgumentInfo> argumentsIterator(String key) {
    MethodEntry entry = map.get(key);
    return entry != null ? entry.arguments : null;
  }

  public String getDescription(String key) {
    MethodEntry entry = map.get(key);
    return entry == null ? null : entry.description;
  }

  @Override
  public ResourceEntry getEntry(String key) {
    MethodEntry entry = map.get(key);
    return entry == null ? null : new EntryWrapper(key, entry);
  }

  @Override
  public Collection<String> getExtensions(String key) {
    MethodEntry entry = map.get(key);
    return entry == null ? new ArrayList<String>() : entry.pluralText.keySet();
  }

  public String getMeaning(String key) {
    MethodEntry entry = map.get(key);
    return entry == null ? null : entry.meaning;
  }

  @Override
  public String getStringExt(String key, String extension) {
    MethodEntry entry = map.get(key);
    if (entry == null) {
      return null;
    }
    if (extension != null) {
      return entry.pluralText.get(extension);
    } else {
      return entry.text;
    }
  }

  @Override
  public boolean notEmpty() {
    return !map.isEmpty();
  }

  @Override
  public String toString() {
    return "Annotations from class " + getPath() + " @" + getMatchLocale();
  }
}
