/*
 * 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.user.rebind.ui;

import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.Generator.RunsLocal;
import com.google.gwt.core.ext.GeneratorContext;
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.user.client.ui.ImageBundle;
import com.google.gwt.user.client.ui.ImageBundle.Resource;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

import java.io.PrintWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * Generates an implementation of a user-defined interface <code>T</code> that
 * extends {@link com.google.gwt.user.client.ui.ImageBundle}.
 *
 * Each method in <code>T</code> must be declared to return
 * {@link com.google.gwt.user.client.ui.AbstractImagePrototype}, take no
 * parameters, and optionally specify the metadata tag <code>gwt.resource</code>
 * as the name of an image that can be found in the classpath. In the absence of
 * the metatadata tag, the method name with an extension of
 * <code>.png, .jpg, or .gif</code> defines the name of the image, and the
 * image file must be located in the same package as <code>T</code>.
 */
@RunsLocal
public class ImageBundleGenerator extends Generator {

  /**
   * Simple wrapper around JMethod that allows for unit test mocking.
   */
  interface JMethodOracle {

    @SuppressWarnings("deprecation")
    Resource getAnnotation(Class<Resource> clazz);

    String getName();

    String getPackageName();
  }

  /**
   * Indirection around the act of looking up a resource that allows for unit
   * test mocking.
   */
  /* private */interface ResourceLocator {
    /**
     *
     * @param resName the resource name in a format that could be passed to
     *          <code>ClassLoader.getResource()</code>
     * @return <code>true</code> if the resource is present
     */
    boolean isResourcePresent(String resName);
  }

  private static class JMethodOracleImpl implements JMethodOracle {
    private final JMethod delegate;

    public JMethodOracleImpl(JMethod delegate) {
      this.delegate = delegate;
    }

    @SuppressWarnings("deprecation")
    public Resource getAnnotation(Class<Resource> clazz) {
      return delegate.getAnnotation(clazz);
    }

    public String getName() {
      return delegate.getName();
    }

    public String getPackageName() {
      return delegate.getEnclosingType().getPackage().getName();
    }
  }

  /* private */static final String MSG_NO_FILE_BASED_ON_METHOD_NAME = "No matching image resource was found; any of the following filenames would have matched had they been present:";

  private static final String ABSTRACTIMAGEPROTOTYPE_QNAME = "com.google.gwt.user.client.ui.AbstractImagePrototype";

  private static final String CLIPPEDIMAGEPROTOTYPE_QNAME = "com.google.gwt.user.client.ui.impl.ClippedImagePrototype";

  private static final String GWT_QNAME = "com.google.gwt.core.client.GWT";

  private static final String[] IMAGE_FILE_EXTENSIONS = {"png", "gif", "jpg"};

  private static final String IMAGEBUNDLE_QNAME = "com.google.gwt.user.client.ui.ImageBundle";

  /* private */static String msgCannotFindImageFromMetaData(String imgResName) {
    return "Unable to find image resource '" + imgResName + "'";
  }

  private final ResourceLocator resLocator;

  /**
   * Default constructor for image bundle. Locates resources using this class's
   * own class loader.
   */
  public ImageBundleGenerator() {
    this(new ResourceLocator() {
      public boolean isResourcePresent(String resName) {
        URL url = getClass().getClassLoader().getResource(resName);
        return url != null;
      }
    });
  }

  /**
   * Default access so that it can be accessed by unit tests.
   */
  /* private */ImageBundleGenerator(ResourceLocator resourceLocator) {
    assert (resourceLocator != null);
    this.resLocator = resourceLocator;
  }

  @Override
  public String generate(TreeLogger logger, GeneratorContext context,
      String typeName) throws UnableToCompleteException {

    TypeOracle typeOracle = context.getTypeOracle();

    // Get metadata describing the user's class.
    JClassType userType = getValidUserType(logger, typeName, typeOracle);

    // Write the new class.
    JMethod[] imgMethods = userType.getOverridableMethods();
    String resultName = generateImplClass(logger, context, userType, imgMethods);

    // Return the complete name of the generated class.
    return resultName;
  }

  /**
   * Gets the resource name of the image associated with the specified image
   * bundle method in a form that can be passed to
   * <code>ClassLoader.getResource()</code>.
   *
   * @param logger the main logger
   * @param method the image bundle method whose image name is being sought
   * @return a resource name that is suitable to be passed into
   *         <code>ClassLoader.getResource()</code>; never returns
   *         <code>null</code>
   * @throws UnableToCompleteException thrown if a resource was specified but
   *           could not be found on the classpath
   */
  /* private */String getImageResourceName(TreeLogger logger,
      JMethodOracle method) throws UnableToCompleteException {
    String imgName = tryGetImageNameFromMetaData(logger, method);
    if (imgName != null) {
      return imgName;
    } else {
      return getImageNameFromMethodName(logger, method);
    }
  }

  private String computeSubclassName(JClassType userType) {
    String baseName = userType.getName().replace('.', '_');
    return baseName + "_generatedBundle";
  }

  private void generateImageMethod(ImageBundleBuilder compositeImage,
      SourceWriter sw, JMethod method, String imgResName) {

    String decl = method.getReadableDeclaration(false, true, true, true, true);

    {
      sw.indent();

      // Create a singleton that this method can return. There is no need to
      // create a new instance every time this method is called, since
      // ClippedImagePrototype is immutable

      ImageBundleBuilder.ImageRect imageRect = compositeImage.getMapping(imgResName);
      String singletonName = method.getName() + "_SINGLETON";

      sw.print("private static final ClippedImagePrototype ");
      sw.print(singletonName);
      sw.print(" = new ClippedImagePrototype(IMAGE_BUNDLE_URL, ");
      sw.print(Integer.toString(imageRect.getLeft()));
      sw.print(", ");
      sw.print(Integer.toString(imageRect.getTop()));
      sw.print(", ");
      sw.print(Integer.toString(imageRect.getWidth()));
      sw.print(", ");
      sw.print(Integer.toString(imageRect.getHeight()));
      sw.println(");");

      sw.print(decl);
      sw.println(" {");

      {
        sw.indent();
        sw.print("return ");
        sw.print(singletonName);
        sw.println(";");
        sw.outdent();
      }

      sw.println("}");
      sw.outdent();
    }
  }

  /**
   * Generates the image bundle implementation class, checking each method for
   * validity as it is encountered.
   */
  private String generateImplClass(TreeLogger logger, GeneratorContext context,
      JClassType userType, JMethod[] imageMethods)
      throws UnableToCompleteException {
    // Lookup the type info for AbstractImagePrototype so that we can check for
    // the proper return type
    // on image bundle methods.
    final JClassType abstractImagePrototype;
    try {
      abstractImagePrototype = userType.getOracle().getType(
          ABSTRACTIMAGEPROTOTYPE_QNAME);
    } catch (NotFoundException e) {
      logger.log(TreeLogger.ERROR, "GWT " + ABSTRACTIMAGEPROTOTYPE_QNAME
          + " class is not available", e);
      throw new UnableToCompleteException();
    }

    // Compute the package and class names of the generated class.
    String pkgName = userType.getPackage().getName();
    String subName = computeSubclassName(userType);

    // Begin writing the generated source.
    ClassSourceFileComposerFactory f = new ClassSourceFileComposerFactory(
        pkgName, subName);
    f.addImport(ABSTRACTIMAGEPROTOTYPE_QNAME);
    f.addImport(CLIPPEDIMAGEPROTOTYPE_QNAME);
    f.addImport(GWT_QNAME);
    f.addImplementedInterface(userType.getQualifiedSourceName());

    PrintWriter pw = context.tryCreate(logger, pkgName, subName);
    if (pw != null) {
      SourceWriter sw = f.createSourceWriter(context, pw);

      // Build a compound image from each individual image.
      ImageBundleBuilder bulder = new ImageBundleBuilder();

      // Store the computed image names so that we don't have to lookup them up
      // again.
      List<String> imageResNames = new ArrayList<String>();

      for (JMethod method : imageMethods) {
        String branchMsg = "Analyzing method '" + method.getName()
            + "' in type " + userType.getQualifiedSourceName();
        TreeLogger branch = logger.branch(TreeLogger.DEBUG, branchMsg, null);

        // Verify that this method is valid on an image bundle.
        if (method.getReturnType() != abstractImagePrototype) {
          branch.log(TreeLogger.ERROR, "Return type must be "
              + ABSTRACTIMAGEPROTOTYPE_QNAME, null);
          throw new UnableToCompleteException();
        }

        if (method.getParameters().length > 0) {
          branch.log(TreeLogger.ERROR, "Method must have zero parameters", null);
          throw new UnableToCompleteException();
        }

        // Find the associated imaged resource.
        String imageResName = getImageResourceName(branch,
            new JMethodOracleImpl(method));
        assert (imageResName != null);
        imageResNames.add(imageResName);
        bulder.assimilate(logger, imageResName);
      }

      // Write the compound image into the output directory.
      String bundledImageUrl = bulder.writeBundledImage(logger, context);

      // Emit a constant for the composite URL. Note that we prepend the
      // module's base URL so that the module can reference its own resources
      // independently of the host HTML page.
      sw.print("private static final String IMAGE_BUNDLE_URL = GWT.getModuleBaseURL() + \"");
      sw.print(escape(bundledImageUrl));
      sw.println("\";");

      // Generate an implementation of each method.
      int imageResNameIndex = 0;
      for (JMethod method : imageMethods) {
        generateImageMethod(bulder, sw, method,
            imageResNames.get(imageResNameIndex++));
      }

      // Finish.
      sw.commit(logger);
    }

    return f.getCreatedClassName();
  }

  /**
   * Attempts to get the image name from the name of the method itself by
   * speculatively appending various image-like file extensions in a prioritized
   * order. The first image found, if any, is used.
   *
   * @param logger if no matching image resource is found, an explanatory
   *          message will be logged
   * @param method the method whose name is being examined for matching image
   *          resources
   * @return a resource name that is suitable to be passed into
   *         <code>ClassLoader.getResource()</code>; never returns
   *         <code>null</code>
   * @throws UnableToCompleteException thrown when no image can be found based
   *           on the method name
   */
  private String getImageNameFromMethodName(TreeLogger logger,
      JMethodOracle method) throws UnableToCompleteException {
    String pkgName = method.getPackageName();
    String pkgPrefix = pkgName.replace('.', '/');
    if (pkgPrefix.length() > 0) {
      pkgPrefix += "/";
    }
    String methodName = method.getName();
    String pkgAndMethodName = pkgPrefix + methodName;
    List<String> testImgNames = new ArrayList<String>();
    for (int i = 0; i < IMAGE_FILE_EXTENSIONS.length; i++) {
      String testImgName = pkgAndMethodName + '.' + IMAGE_FILE_EXTENSIONS[i];
      if (resLocator.isResourcePresent(testImgName)) {
        return testImgName;
      }
      testImgNames.add(testImgName);
    }

    TreeLogger branch = logger.branch(TreeLogger.ERROR,
        MSG_NO_FILE_BASED_ON_METHOD_NAME, null);
    for (String testImgName : testImgNames) {
      branch.log(TreeLogger.ERROR, testImgName, null);
    }

    throw new UnableToCompleteException();
  }

  private JClassType getValidUserType(TreeLogger logger, String typeName,
      TypeOracle typeOracle) throws UnableToCompleteException {
    try {
      // Get the type that the user is introducing.
      JClassType userType = typeOracle.getType(typeName);

      // Get the type this generator is designed to support.
      JClassType markerType = typeOracle.findType(IMAGEBUNDLE_QNAME);

      // Ensure it's an interface.
      if (userType.isInterface() == null) {
        logger.log(TreeLogger.ERROR, userType.getQualifiedSourceName()
            + " must be an interface", null);
        throw new UnableToCompleteException();
      }

      // Ensure proper derivation.
      if (!userType.isAssignableTo(markerType)) {
        logger.log(TreeLogger.ERROR, userType.getQualifiedSourceName()
            + " must be assignable to " + markerType.getQualifiedSourceName(),
            null);
        throw new UnableToCompleteException();
      }

      return userType;

    } catch (NotFoundException e) {
      logger.log(TreeLogger.ERROR, "Unable to find required type(s)", e);
      throw new UnableToCompleteException();
    }
  }

  /**
   * Attempts to get the image name (verbatim) from an annotation.
   *
   * @return the string specified in in the {@link ImageBundle.Resource}
   *         annotation, or <code>null</code>
   */
  @SuppressWarnings("deprecation")
  private String tryGetImageNameFromAnnotation(JMethodOracle method) {
    ImageBundle.Resource imgResAnn = method.getAnnotation(ImageBundle.Resource.class);
    String imgName = null;
    if (imgResAnn != null) {
      imgName = imgResAnn.value();
    }
    return imgName;
  }

  /**
   * Attempts to get the image name from an annotation.
   *
   * @param logger if an annotation is found but the specified resource isn't
   *          available, an error is logged
   * @param method the image bundle method whose associated image resource is
   *          being sought
   * @return a resource name that is suitable to be passed into
   *         <code>ClassLoader.getResource()</code>, or <code>null</code>
   *         if metadata wasn't provided
   * @throws UnableToCompleteException thrown when metadata is provided but the
   *           resource cannot be found
   */
  private String tryGetImageNameFromMetaData(TreeLogger logger,
      JMethodOracle method) throws UnableToCompleteException {
    String imgFileName = tryGetImageNameFromAnnotation(method);
    if (imgFileName == null) {
      // Exit early because neither an annotation nor javadoc was found.
      return null;
    }

    // If the name has no slashes (that is, it isn't a fully-qualified resource
    // name), then prepend the enclosing package name automatically, being
    // careful about the default package.
    if (imgFileName.indexOf("/") == -1) {
      String pkgName = method.getPackageName();
      if (!"".equals(pkgName)) {
        imgFileName = pkgName.replace('.', '/') + "/" + imgFileName;
      }
    }

    if (!resLocator.isResourcePresent(imgFileName)) {
      // Not found.
      logger.log(TreeLogger.ERROR, msgCannotFindImageFromMetaData(imgFileName),
          null);
      throw new UnableToCompleteException();
    }

    // Success.
    return imgFileName;
  }
}
