/*
 * 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.linker.EmittedArtifact.Visibility;
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.server.KeyGenerator;
import com.google.gwt.i18n.server.MessageCatalogFactory;
import com.google.gwt.i18n.server.MessageInterface;
import com.google.gwt.i18n.server.MessageProcessingException;
import com.google.gwt.i18n.server.MessageCatalogFactory.Context;
import com.google.gwt.i18n.server.MessageCatalogFactory.Writer;
import com.google.gwt.i18n.shared.GwtLocale;
import com.google.gwt.i18n.shared.GwtLocaleFactory;
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.IOException;
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.
 */
@SuppressWarnings("deprecation")
abstract class AbstractLocalizableImplCreator extends
    AbstractGeneratorClassCreator {

  public static class MessageCatalogContextImpl
      implements Context {

    private final GeneratorContext context;
    private final TreeLogger logger;

    public MessageCatalogContextImpl(GeneratorContext context,
        TreeLogger logger) {
      this.context = context;
      this.logger = logger;
    }

    public OutputStream createBinaryFile(String catalogName) {
      try {
        final OutputStream ostr = context.tryCreateResource(logger, catalogName);
        if (ostr != null) {
          // wrap the stream so we can commit the resource on close
          return new OutputStream() {

            @Override
            public void close() throws IOException {
              try {
                context.commitResource(logger, ostr).setVisibility(
                    Visibility.Private);
              } catch (UnableToCompleteException e) {
                // error already logged, anything more to do?
              }
            }

            @Override
            public void write(byte[] b, int off, int len) throws IOException {
              ostr.write(b, off, len);
            }

            @Override
            public void write(int b) throws IOException {
              ostr.write(b);
            }
          };
        }
      } catch (UnableToCompleteException e) {
        // error already logged, anything more to do?
      }
      return null;
    }

    public PrintWriter createTextFile(String catalogName, String charSet) {
      OutputStream outStr = createBinaryFile(catalogName);
      if (outStr != null) {
        try {
          return new PrintWriter(new BufferedWriter(
              new OutputStreamWriter(outStr, "UTF-8")), false);
        } catch (UnsupportedEncodingException e) {
          error("UTF-8 not supported", e);
        }
      }
      return null;
    }

    public void error(String msg) {
      logger.log(TreeLogger.ERROR, msg);
    }

    public void error(String msg, Throwable cause) {
      logger.log(TreeLogger.ERROR, msg, cause);
    }

    public GwtLocaleFactory getLocaleFactory() {
      return LocaleUtils.getLocaleFactory();
    }

    public void warning(String msg) {
      logger.log(TreeLogger.WARN, msg);
    }

    public void warning(String msg, Throwable cause) {
      logger.log(TreeLogger.WARN, msg, cause);
    }
  }

  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;
          MessageCatalogFactory msgCatFactory = null;
          try {
            // TODO(jat): if GWT is ever modified to take a classpath for user
            // code as an option, we would need to use the user classloader here
            Class<?> clazz = Class.forName(genClassName, false,
                MessageCatalogFormat.class.getClassLoader());
            if (MessageCatalogFormat.class.isAssignableFrom(clazz)) {
              Class<? extends MessageCatalogFormat> msgFormatClass
                  = clazz.asSubclass(MessageCatalogFormat.class);
              msgWriter = msgFormatClass.newInstance();
            } else if (MessageCatalogFactory.class.isAssignableFrom(clazz)) {
              Class<? extends MessageCatalogFactory> msgFactoryClass
                  = clazz.asSubclass(MessageCatalogFactory.class);
              msgCatFactory = msgFactoryClass.newInstance();
            } else {
              logger.log(TreeLogger.ERROR, "Class specified in @Generate must "
                  + "either be a subtype of MessageCatalogFormat or "
                  + "MessageCatalogFactory");
              seenError = true;
              continue;
            }
          } 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();
          }
          if (msgCatFactory != null) {
            seenError |= generateToMsgCatFactory(logger, context, locale,
                targetClass, seenError, resourceList, msgCatFactory, genPath);
          } else if (msgWriter != null) {
            seenError |= generateToLegacyMsgCatFormat(logger, context, locale,
                targetClass, seenError, resourceList, className, msgWriter,
                genPath);
          }
        }
      }
    }
    if (seenError) {
      // If one of our generators had a fatal error, don't complete normally.
      throw new UnableToCompleteException();
    }
    return packageName + "." + className;
  }

  /**
   * Write translation source files to the old-style
   * {@link MessageCatalogFormat}.
   *
   * @param logger
   * @param context
   * @param locale
   * @param targetClass
   * @param seenError
   * @param resourceList
   * @param className
   * @param msgWriter
   * @param genPath
   * @return true if an error occurred (already logged)
   * @throws UnableToCompleteException
   */
  
  private static boolean generateToLegacyMsgCatFormat(TreeLogger logger,
      GeneratorContext context, GwtLocale locale, JClassType targetClass,
      boolean seenError, ResourceList resourceList, String className,
      MessageCatalogFormat msgWriter, String genPath)
      throws UnableToCompleteException {
    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, "UTF-8 not supported", e);
      }
      try {
        msgWriter.write(branch, locale.toString(), resourceList, out,
            targetClass);
        out.flush();
        context.commitResource(logger, outStr).setVisibility(
            Visibility.Private);
      } catch (UnableToCompleteException e) {
        // msgWriter should have already logged an error message.
        // Keep going for now so we can find other errors.
        seenError = true;
      }
    }
    return seenError;
  }

  /**
   * Write translation source files to a {@link MessageCatalogFactory}.
   *
   * @param logger
   * @param context
   * @param locale 
   * @param targetClass
   * @param seenError
   * @param resourceList
   * @param msgCatFactory
   * @param genPath
   * @return true if an error occurred (already logged)
   */
  private static boolean generateToMsgCatFactory(TreeLogger logger,
      GeneratorContext context, GwtLocale locale, JClassType targetClass, boolean seenError,
      ResourceList resourceList, MessageCatalogFactory msgCatFactory,
      String genPath) {
    // TODO(jat): maintain MessageCatalogWriter instances across
    // generator runs so they can save state.  One problem is knowing
    // when the last generator has been run.
    Writer catWriter = null;
    try {
      String catalogName = genPath + msgCatFactory.getExtension();
      Context ctx = new MessageCatalogContextImpl(
          context, logger);
      MessageInterface msgIntf = new TypeOracleMessageInterface(
          LocaleUtils.getLocaleFactory(), targetClass, resourceList);
      catWriter = msgCatFactory.getWriter(ctx, catalogName);
      if (catWriter == null) {
        logger.log(TreeLogger.TRACE, "Already generated " + catalogName);
        return false;
      }
      msgIntf.accept(catWriter.visitClass());
    } catch (MessageProcessingException e) {
      logger.log(TreeLogger.ERROR, e.getMessage(), e);
      seenError = true;
    } finally {
      if (catWriter != null) {
        try {
          catWriter.close();
        } catch (IOException e) {
          logger.log(TreeLogger.ERROR,
              "IO error closing catalog writer", e);
          seenError = true;
        }
      }
    }
    return seenError;
  }

  /**
   * 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);
  }
}
