/*
 * 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.BadPropertyValueException;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.SelectionProperty;
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.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.i18n.client.LocalizableResource.Generate;
import com.google.gwt.i18n.client.LocalizableResource.Key;
import com.google.gwt.i18n.rebind.AbstractResource.ResourceList;
import com.google.gwt.i18n.rebind.AnnotationsResource.AnnotationsError;
import com.google.gwt.i18n.rebind.format.MessageCatalogFormat;
import com.google.gwt.i18n.rebind.keygen.KeyGenerator;
import com.google.gwt.i18n.shared.GwtLocale;
import com.google.gwt.user.rebind.AbstractGeneratorClassCreator;
import com.google.gwt.user.rebind.AbstractMethodCreator;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

import java.io.BufferedWriter;
import java.io.File;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.MissingResourceException;

/**
 * Represents generic functionality needed for <code>Constants</code> and
 * <code>Messages</code> classes.
 */
abstract class AbstractLocalizableImplCreator extends
    AbstractGeneratorClassCreator {

  static String generateConstantOrMessageClass(TreeLogger logger,
      GeneratorContext context, GwtLocale locale, JClassType targetClass)
      throws UnableToCompleteException {
    TypeOracle oracle = context.getTypeOracle();
    JClassType constantsClass;
    JClassType messagesClass;
    JClassType constantsWithLookupClass;
    boolean seenError = false;
    try {
      constantsClass = oracle.getType(LocalizableGenerator.CONSTANTS_NAME);
      constantsWithLookupClass = oracle.getType(LocalizableGenerator.CONSTANTS_WITH_LOOKUP_NAME);
      messagesClass = oracle.getType(LocalizableGenerator.MESSAGES_NAME);
    } catch (NotFoundException e) {
      // Should never happen in practice.
      throw error(logger, e);
    }

    String name = targetClass.getName();
    String packageName = targetClass.getPackage().getName();

    // Make sure the interface being rebound extends either Constants or
    // Messages.
    boolean assignableToConstants = constantsClass.isAssignableFrom(targetClass);
    boolean assignableToMessages = messagesClass.isAssignableFrom(targetClass);
    if (!assignableToConstants && !assignableToMessages) {
      // Let the implementation generator handle this interface.
      return null;
    }

    // Make sure that they don't try to extend both Messages and Constants.
    if (assignableToConstants && assignableToMessages) {
      throw error(logger, name + " cannot extend both Constants and Messages");
    }

    // Make sure that the type being rebound is in fact an interface.
    if (targetClass.isInterface() == null) {
      throw error(logger, name + " must be an interface");
    }

    ResourceList resourceList = null;
    try {
      resourceList = ResourceFactory.getBundle(logger, targetClass, locale,
          assignableToConstants, context.getResourcesOracle().getResourceMap(), context);
    } catch (MissingResourceException e) {
      throw error(logger,
          "Localization failed; there must be at least one resource accessible through"
              + " the classpath in package '" + packageName
              + "' whose base name is '"
              + ResourceFactory.getResourceName(targetClass) + "'");
    } catch (IllegalArgumentException e) {
      // A bad key can generate an illegal argument exception.
      throw error(logger, e.getMessage());
    }

    // generated implementations for interface X will be named X_, X_en,
    // X_en_CA, etc.
    GwtLocale generatedLocale = resourceList.findLeastDerivedLocale(logger,
        locale);
    String localeSuffix = String.valueOf(ResourceFactory.LOCALE_SEPARATOR);
    localeSuffix += generatedLocale.getAsString();
    // Use _ rather than "." in class name, cannot use $
    String resourceName = targetClass.getName().replace('.', '_');
    String className = resourceName + localeSuffix;
    PrintWriter pw = context.tryCreate(logger, packageName, className);
    if (pw != null) {
      ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(
          packageName, className);
      factory.addImplementedInterface(targetClass.getQualifiedSourceName());
      SourceWriter writer = factory.createSourceWriter(context, pw);
      // Now that we have all the information set up, process the class
      if (constantsWithLookupClass.isAssignableFrom(targetClass)) {
        ConstantsWithLookupImplCreator c = new ConstantsWithLookupImplCreator(
            logger, writer, targetClass, resourceList, context.getTypeOracle());
        c.emitClass(logger, generatedLocale);
      } else if (constantsClass.isAssignableFrom(targetClass)) {
        ConstantsImplCreator c = new ConstantsImplCreator(logger, writer,
            targetClass, resourceList, context.getTypeOracle());
        c.emitClass(logger, generatedLocale);
      } else {
        MessagesImplCreator messages = new MessagesImplCreator(logger, writer,
            targetClass, resourceList, context.getTypeOracle());
        messages.emitClass(logger, generatedLocale);
      }
      context.commit(logger, pw);
    }
    // Generate a translatable output file if requested.
    Generate generate = getClassAnnotation(targetClass, Generate.class);
    if (generate != null) {
      String path = generate.fileName();
      if (Generate.DEFAULT.equals(path)) {
        path = targetClass.getPackage().getName() + "."
            + targetClass.getName().replace('.', '_');
      } else if (path.endsWith(File.pathSeparator)) {
        path = path + targetClass.getName().replace('.', '_');
      }
      String[] genLocales = generate.locales();
      boolean found = false;
      if (genLocales.length != 0) {
        // verify the current locale is in the list
        for (String genLocale : genLocales) {
          if (GwtLocale.DEFAULT_LOCALE.equals(genLocale)) {
            // Locale "default" gets special handling because of property
            // fallbacks; "default" might be mapped to any real locale.
            try {
              SelectionProperty localeProp = 
                  context.getPropertyOracle().getSelectionProperty(logger, "locale");
              String defaultLocale = localeProp.getFallbackValue();
              if (defaultLocale.length() > 0) {
                genLocale = defaultLocale;
              }
            } catch (BadPropertyValueException e) {
              throw error(logger, "Could not get 'locale' property");
            }
          }
          if (genLocale.equals(locale.toString())) {
            found = true;
            break;
          }
        }
      } else {
        // Since they want all locales, this is guaranteed to be one of them.
        found = true;
      }
      if (found) {
        for (String genClassName : generate.format()) {
          MessageCatalogFormat msgWriter = null;
          try {
            Class<? extends MessageCatalogFormat> msgFormatClass = Class.forName(
                genClassName, false,
                MessageCatalogFormat.class.getClassLoader()).asSubclass(
                MessageCatalogFormat.class);
            msgWriter = msgFormatClass.newInstance();
          } catch (InstantiationException e) {
            logger.log(TreeLogger.ERROR, "Error instantiating @Generate class "
                + genClassName, e);
            seenError = true;
            continue;
          } catch (IllegalAccessException e) {
            logger.log(TreeLogger.ERROR, "@Generate class " + genClassName
                + " illegal access", e);
            seenError = true;
            continue;
          } catch (ClassNotFoundException e) {
            logger.log(TreeLogger.ERROR, "@Generate class " + genClassName
                + " not found");
            seenError = true;
            continue;
          }
          // Make generator-specific changes to a temporary copy of the path.
          String genPath = path;
          if (genLocales.length != 1) {
            // If the user explicitly specified only one locale, do not add the
            // locale.
            genPath += '_' + locale.toString();
          }
          genPath += msgWriter.getExtension();
          OutputStream outStr = context.tryCreateResource(logger, genPath);
          if (outStr != null) {
            TreeLogger branch = logger.branch(TreeLogger.TRACE, "Generating "
                + genPath + " from " + className + " for locale " + locale,
                null);
            PrintWriter out = null;
            try {
              out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                  outStr, "UTF-8")), false);
            } catch (UnsupportedEncodingException e) {
              throw error(logger, e.getMessage());
            }
            try {
              // TODO(jat): change writer interface to use GwtLocale
              msgWriter.write(branch, locale.toString(), resourceList, out,
                  targetClass);
              out.flush();
              context.commitResource(logger, outStr).setPrivate(true);
            } catch (UnableToCompleteException e) {
              // msgWriter should have already logged an error message.
              // Keep going for now so we can find other errors.
              seenError = true;
            }
          }
        }
      }
    }
    if (seenError) {
      // If one of our generators had a fatal error, don't complete normally.
      throw new UnableToCompleteException();
    }
    return packageName + "." + className;
  }

  /**
   * Generator to use to create keys for messages.
   */
  private KeyGenerator keyGenerator;

  /**
   * The Dictionary/value bindings used to determine message contents.
   */
  private ResourceList resourceList;

  /**
   * True if the class being generated uses Constants-style annotations/quoting.
   */
  private boolean isConstants;

  /**
   * Constructor for <code>AbstractLocalizableImplCreator</code>.
   * 
   * @param writer writer
   * @param targetClass current target
   * @param resourceList backing resource
   */
  public AbstractLocalizableImplCreator(TreeLogger logger, SourceWriter writer,
      JClassType targetClass, ResourceList resourceList, boolean isConstants) {
    super(writer, targetClass);
    this.resourceList = resourceList;
    this.isConstants = isConstants;
    try {
      keyGenerator = AnnotationsResource.getKeyGenerator(targetClass);
    } catch (AnnotationsError e) {
      logger.log(TreeLogger.WARN, "Error getting key generator for "
          + targetClass.getQualifiedSourceName(), e);
    }
  }

  /**
   * Gets the resource associated with this class.
   * 
   * @return the resource
   */
  public ResourceList getResourceBundle() {
    return resourceList;
  }

  @Override
  protected String branchMessage() {
    return "Processing " + this.getTarget();
  }

  /**
   * Find the creator associated with the given method, and delegate the
   * creation of the method body to it.
   * 
   * @param logger TreeLogger instance for logging
   * @param method method to be generated
   * @param locale locale to generate
   * @throws UnableToCompleteException
   */
  protected void delegateToCreator(TreeLogger logger, JMethod method,
      GwtLocale locale) throws UnableToCompleteException {
    AbstractMethodCreator methodCreator = getMethodCreator(logger, method);
    String key = getKey(logger, method);
    if (key == null) {
      logger.log(TreeLogger.ERROR, "Unable to get or compute key for method "
          + method.getName(), null);
      throw new UnableToCompleteException();
    }
    methodCreator.createMethodFor(logger, method, key, resourceList, locale);
  }

  /**
   * Returns a resource key given a method name.
   * 
   * @param logger TreeLogger instance for logging
   * @param method method to get key for
   * @return the key to use for resource lookups or null if unable to get or
   *         compute the key
   */
  protected String getKey(TreeLogger logger, JMethod method) {
    Key key = method.getAnnotation(Key.class);
    if (key != null) {
      return key.value();
    }
    return AnnotationsResource.getKey(logger, keyGenerator, method, isConstants);
  }
}
