/*
 * 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.resources.ext;

import com.google.gwt.core.ext.BadPropertyValueException;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.PropertyOracle;
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.JPackage;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.dev.util.collect.Maps;
import com.google.gwt.resources.client.ClientBundle.Source;

import java.io.File;
import java.lang.annotation.Annotation;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Utility methods for building ResourceGenerators.
 */
public final class ResourceGeneratorUtil {

  private static class ClassLoaderLocator implements Locator {
    private final ClassLoader classLoader;

    public ClassLoaderLocator(ClassLoader classLoader) {
      this.classLoader = classLoader;
    }

    public URL locate(String resourceName) {
      return classLoader.getResource(resourceName);
    }
  }

  /**
   * A locator which will use files published via
   * {@link ResourceGeneratorUtil#addNamedFile(String, File)}.
   */
  private static class NamedFileLocator implements Locator {
    public static final NamedFileLocator INSTANCE = new NamedFileLocator();

    private NamedFileLocator() {
    }

    public URL locate(String resourceName) {
      File f = namedFiles.get(resourceName);
      if (f != null && f.isFile() && f.canRead()) {
        try {
          return f.toURI().toURL();
        } catch (MalformedURLException e) {
          throw new RuntimeException("Unable to make a URL for file "
              + f.getName());
        }
      }
      return null;
    }
  }

  /**
   * Wrapper interface around different strategies for loading resource data.
   */
  private interface Locator {
    URL locate(String resourceName);
  }

  private static class ResourceOracleLocator implements Locator {
    private final Map<String, Resource> resourceMap;

    public ResourceOracleLocator(ResourceOracle oracle) {
      resourceMap = oracle.getResourceMap();
    }

    @SuppressWarnings("deprecation")
    public URL locate(String resourceName) {
      Resource r = resourceMap.get(resourceName);
      return (r == null) ? null : r.getURL();
    }
  }

  private static Map<String, File> namedFiles = Maps.create();

  /**
   * These are type names from previous APIs or from APIs with similar
   * functionality that might be confusing.
   *
   * @see #checkForDeprecatedAnnotations
   */
  private static final String[] DEPRECATED_ANNOTATION_NAMES = {
      "com.google.gwt.libideas.resources.client.ImmutableResourceBundle$Resource",
      "com.google.gwt.user.client.ui.ImageBundle$Resource"};

  private static final List<Class<? extends Annotation>> DEPRECATED_ANNOTATION_CLASSES;

  static {
    List<Class<? extends Annotation>> classes = new ArrayList<Class<? extends Annotation>>(
        DEPRECATED_ANNOTATION_NAMES.length);

    for (String name : DEPRECATED_ANNOTATION_NAMES) {
      try {
        Class<?> maybeAnnotation = Class.forName(name, false,
            ResourceGeneratorUtil.class.getClassLoader());

        // Possibly throws ClassCastException
        Class<? extends Annotation> annotationClass = maybeAnnotation.asSubclass(Annotation.class);

        classes.add(annotationClass);

      } catch (ClassCastException e) {
        // If it's not an Annotation type, we don't care about it
      } catch (ClassNotFoundException e) {
        // This is OK; the annotation doesn't exist.
      }
    }

    if (classes.isEmpty()) {
      DEPRECATED_ANNOTATION_CLASSES = Collections.emptyList();
    } else {
      DEPRECATED_ANNOTATION_CLASSES = Collections.unmodifiableList(classes);
    }
  }

  /**
   * Publish or override resources named by {@link Source} annotations. This
   * method is intended to be called by Generators that create ClientBundle
   * instances and need to pass source data to the ClientBundle system that is
   * not accessible through the classpath.
   *
   * @param resourceName the path at which the contents of <code>file</code>
   *          should be made available
   * @param file the File whose contents are to be provided to the ClientBundle
   *          system
   */
  public static void addNamedFile(String resourceName, File file) {
    assert resourceName != null : "resourceName";
    assert file != null : "file";
    assert file.isFile() && file.canRead() : "file does not exist or cannot be read";

    namedFiles = Maps.put(namedFiles, resourceName, file);
  }

  /**
   * Returns the base filename of a resource. The behavior is similar to the unix
   * command <code>basename</code>.
   *
   * @param resource the URL of the resource
   * @return the final name segment of the resource
   */
  public static String baseName(URL resource) {
    String path = resource.getPath();
    return path.substring(path.lastIndexOf('/') + 1);
  }

  /**
   * Find all resources referenced by a method in a bundle. The method's
   * {@link Source} annotation will be examined and the specified locations will
   * be expanded into URLs by which they may be accessed on the local system.
   * <p>
   * This method is sensitive to the <code>locale</code> deferred-binding
   * property and will attempt to use a best-match lookup by removing locale
   * components.
   * <p>
   * Loading through a ClassLoader with this method is much slower than the
   * other <code>findResources</code> methods which make use of the compiler's
   * ResourceOracle.
   *
   * @param logger a TreeLogger that will be used to report errors or warnings
   * @param context the ResourceContext in which the ResourceGenerator is
   *          operating
   * @param classLoader the ClassLoader to use when locating resources
   * @param method the method to examine for {@link Source} annotations
   * @param defaultSuffixes if the supplied method does not have any
   *          {@link Source} annotations, act as though a Source annotation was
   *          specified, using the name of the method and each of supplied
   *          extensions in the order in which they are specified
   * @return URLs for each {@link Source} annotation value defined on the
   *         method.
   * @throws UnableToCompleteException if ore or more of the sources could not
   *           be found. The error will be reported via the <code>logger</code>
   *           provided to this method
   */
  public static URL[] findResources(TreeLogger logger, ClassLoader classLoader,
      ResourceContext context, JMethod method, String[] defaultSuffixes)
      throws UnableToCompleteException {
    return findResources(logger, new Locator[] {new ClassLoaderLocator(
        classLoader)}, context, method, defaultSuffixes);
  }

  /**
   * Find all resources referenced by a method in a bundle. The method's
   * {@link Source} annotation will be examined and the specified locations will
   * be expanded into URLs by which they may be accessed on the local system.
   * <p>
   * This method is sensitive to the <code>locale</code> deferred-binding
   * property and will attempt to use a best-match lookup by removing locale
   * components.
   * <p>
   * The compiler's ResourceOracle will be used to resolve resource locations.
   * If the desired resource cannot be found in the ResourceOracle, this method
   * will fall back to using the current thread's context ClassLoader. If it is
   * necessary to alter the way in which resources are located, use the overload
   * that accepts a ClassLoader.
   * <p>
   * If the method's return type declares the {@link DefaultExtensions}
   * annotation, the value of this annotation will be used to find matching
   * resource names if the method lacks a {@link Source} annotation.
   *
   * @param logger a TreeLogger that will be used to report errors or warnings
   * @param context the ResourceContext in which the ResourceGenerator is
   *          operating
   * @param method the method to examine for {@link Source} annotations
   * @return URLs for each {@link Source} annotation value defined on the
   *         method.
   * @throws UnableToCompleteException if ore or more of the sources could not
   *           be found. The error will be reported via the <code>logger</code>
   *           provided to this method
   */
  public static URL[] findResources(TreeLogger logger, ResourceContext context,
      JMethod method) throws UnableToCompleteException {
    JClassType returnType = method.getReturnType().isClassOrInterface();
    assert returnType != null;
    DefaultExtensions annotation = returnType.findAnnotationInTypeHierarchy(DefaultExtensions.class);
    String[] extensions;
    if (annotation != null) {
      extensions = annotation.value();
    } else {
      extensions = new String[0];
    }
    return findResources(logger, context, method, extensions);
  }

  /**
   * Find all resources referenced by a method in a bundle. The method's
   * {@link Source} annotation will be examined and the specified locations will
   * be expanded into URLs by which they may be accessed on the local system.
   * <p>
   * This method is sensitive to the <code>locale</code> deferred-binding
   * property and will attempt to use a best-match lookup by removing locale
   * components.
   * <p>
   * The compiler's ResourceOracle will be used to resolve resource locations.
   * If the desired resource cannot be found in the ResourceOracle, this method
   * will fall back to using the current thread's context ClassLoader. If it is
   * necessary to alter the way in which resources are located, use the overload
   * that accepts a ClassLoader.
   *
   * @param logger a TreeLogger that will be used to report errors or warnings
   * @param context the ResourceContext in which the ResourceGenerator is
   *          operating
   * @param method the method to examine for {@link Source} annotations
   * @param defaultSuffixes if the supplied method does not have any
   *          {@link Source} annotations, act as though a Source annotation was
   *          specified, using the name of the method and each of supplied
   *          extensions in the order in which they are specified
   * @return URLs for each {@link Source} annotation value defined on the
   *         method.
   * @throws UnableToCompleteException if ore or more of the sources could not
   *           be found. The error will be reported via the <code>logger</code>
   *           provided to this method
   */
  public static URL[] findResources(TreeLogger logger, ResourceContext context,
      JMethod method, String[] defaultSuffixes)
      throws UnableToCompleteException {
    Locator[] locators = getDefaultLocators(context.getGeneratorContext());
    URL[] toReturn = findResources(logger, locators, context, method,
        defaultSuffixes);
    return toReturn;
  }

  /**
   * Finds a method by following a dotted path interpreted as a series of no-arg
   * method invocations from an instance of a given root type.
   *
   * @param rootType the type from which the search begins
   * @param pathElements a sequence of no-arg method names
   * @param expectedReturnType the expected return type of the method to locate,
   *          or <code>null</code> if no constraint on the return type is
   *          necessary
   *
   * @return the requested JMethod
   * @throws NotFoundException if the requested method could not be found
   */
  public static JMethod getMethodByPath(JClassType rootType,
      List<String> pathElements, JType expectedReturnType)
      throws NotFoundException {
    if (pathElements.isEmpty()) {
      throw new NotFoundException("No path specified");
    }

    JMethod currentMethod = null;
    JType currentType = rootType;
    for (String pathElement : pathElements) {

      JClassType referenceType = currentType.isClassOrInterface();
      if (referenceType == null) {
        throw new NotFoundException("Cannot resolve member " + pathElement
            + " on type " + currentType.getQualifiedSourceName());
      }

      currentMethod = null;
      searchType : for (JClassType searchType : referenceType.getFlattenedSupertypeHierarchy()) {
        for (JMethod method : searchType.getOverloads(pathElement)) {
          if (method.getParameters().length == 0) {
            currentMethod = method;
            break searchType;
          }
        }
      }

      if (currentMethod == null) {
        throw new NotFoundException("Could not find no-arg method named "
            + pathElement + " in type " + currentType.getQualifiedSourceName());
      }
      currentType = currentMethod.getReturnType();
    }

    if (expectedReturnType != null) {
      JPrimitiveType expectedIsPrimitive = expectedReturnType.isPrimitive();
      JClassType expectedIsClassType = expectedReturnType.isClassOrInterface();
      boolean error = false;

      if (expectedIsPrimitive != null) {
        if (!expectedIsPrimitive.equals(currentMethod.getReturnType())) {
          error = true;
        }
      } else {
        JClassType returnIsClassType = currentMethod.getReturnType().isClassOrInterface();
        if (returnIsClassType == null) {
          error = true;
        } else if (!expectedIsClassType.isAssignableFrom(returnIsClassType)) {
          error = true;
        }
      }

      if (error) {
        throw new NotFoundException("Expecting return type "
            + expectedReturnType.getQualifiedSourceName() + " found "
            + currentMethod.getReturnType().getQualifiedSourceName());
      }
    }

    return currentMethod;
  }

  /**
   * Try to find a resource with the given resourceName.  It will use the default
   * search order to locate the resource as is used by {@link #findResources}.
   * 
   * @param logger
   * @param genContext
   * @param resourceContext
   * @param resourceName
   * @return a URL for the resource, if found
   */
  public static URL tryFindResource(TreeLogger logger,
      GeneratorContext genContext, ResourceContext resourceContext,
      String resourceName) {
    String locale = getLocale(logger, genContext);
    Locator[] locators = getDefaultLocators(genContext);
    for (Locator locator : locators) {
      URL toReturn = tryFindResource(locator, resourceContext, resourceName,
          locale);
      if (toReturn != null) {
        return toReturn;
      }
    }
    return null;
  }

  /**
   * Add the type dependency requirements for a method, to the context.
   * 
   * @param context
   * @param method
   */
  private static void addTypeRequirementsForMethod(ResourceContext context,
      JMethod method) {
    ClientBundleRequirements reqs = context.getRequirements();
    if (reqs != null) {
      reqs.addTypeHierarchy(method.getEnclosingType());
      reqs.addTypeHierarchy((JClassType) method.getReturnType());
    }
  }

  /**
   * We want to warn the user about any annotations from ImageBundle or the old
   * incubator code.
   */
  private static void checkForDeprecatedAnnotations(TreeLogger logger,
      JMethod method) {

    for (Class<? extends Annotation> annotationClass : DEPRECATED_ANNOTATION_CLASSES) {
      if (method.isAnnotationPresent(annotationClass)) {
        logger.log(TreeLogger.WARN, "Deprecated annotation used; expecting "
            + Source.class.getCanonicalName() + " but found "
            + annotationClass.getName() + " instead.  It is likely "
            + "that undesired operation will occur.");
      }
    }
  }

  /**
   * Main implementation of findResources.
   */
  private static URL[] findResources(TreeLogger logger, Locator[] locators,
      ResourceContext context, JMethod method, String[] defaultSuffixes)
      throws UnableToCompleteException {
    logger = logger.branch(TreeLogger.DEBUG, "Finding resources");

    String locale = getLocale(logger, context.getGeneratorContext());

    checkForDeprecatedAnnotations(logger, method);

    boolean error = false;
    Source resourceAnnotation = method.getAnnotation(Source.class);
    URL[] toReturn;

    if (resourceAnnotation == null) {
      if (defaultSuffixes != null) {
        for (String extension : defaultSuffixes) {
          if (logger.isLoggable(TreeLogger.SPAM)) {
            logger.log(TreeLogger.SPAM, "Trying default extension " + extension);
          }
          for (Locator locator : locators) {
            URL resourceUrl = tryFindResource(locator, context,
                getPathRelativeToPackage(method.getEnclosingType().getPackage(),
                    method.getName() + extension), locale);

            // Take the first match
            if (resourceUrl != null) {
              addTypeRequirementsForMethod(context, method);
              return new URL[] {resourceUrl};
            }
          }
        }
      }

      logger.log(TreeLogger.ERROR, "No " + Source.class.getName()
          + " annotation and no resources found with default extensions");
      toReturn = null;
      error = true;

    } else {
      // The user has put an @Source annotation on the accessor method
      String[] resources = resourceAnnotation.value();

      toReturn = new URL[resources.length];

      int tagIndex = 0;
      for (String resource : resources) {
        // Try to find the resource relative to the package.
        URL resourceURL = null;

        for (Locator locator : locators) {
          resourceURL = tryFindResource(locator, context,
              getPathRelativeToPackage(method.getEnclosingType().getPackage(),
                  resource), locale);

          /*
           * If we didn't find the resource relative to the package, assume it
           * is absolute.
           */
          if (resourceURL == null) {
            resourceURL = tryFindResource(locator, context, resource, locale);
          }

          // If we have found a resource, take the first match
          if (resourceURL != null) {
            break;
          }
        }

        if (resourceURL == null) {
          error = true;
          logger.log(TreeLogger.ERROR, "Resource " + resource
              + " not found. Is the name specified as Class.getResource()"
              + " would expect?");
        }

        toReturn[tagIndex++] = resourceURL;
      }
    }

    if (error) {
      throw new UnableToCompleteException();
    }

    addTypeRequirementsForMethod(context, method);
    return toReturn;
  }

  /**
   * Get default list of resource Locators, in the default order.
   * 
   * @param context
   * @return an ordered array of Locator[]
   */
  private static Locator[] getDefaultLocators(GeneratorContext genContext) {
    Locator[] locators = {
      NamedFileLocator.INSTANCE,
      new ResourceOracleLocator(genContext.getResourcesOracle()),
      new ClassLoaderLocator(Thread.currentThread().getContextClassLoader())};

    return locators;
  }

  /**
   * Get the current locale string.
   * 
   * @param logger
   * @param context
   * @return the current locale
   */
  private static String getLocale(TreeLogger logger, GeneratorContext genContext) {
    String locale;
    try {
      PropertyOracle oracle = genContext.getPropertyOracle();
      SelectionProperty prop = oracle.getSelectionProperty(logger, "locale");
      locale = prop.getCurrentValue();
    } catch (BadPropertyValueException e) {
      locale = null;
    }
    return locale;
  }
 
  /**
   * Converts a package relative path into an absolute path.
   *
   * @param pkg the package
   * @param path a path relative to the package
   * @return an absolute path
   */
  private static String getPathRelativeToPackage(JPackage pkg, String path) {
    return pkg.getName().replace('.', '/') + '/' + path;
  }

  /**
   * This performs the locale lookup function for a given resource name.
   *
   * @param locator the Locator to use to load the resources
   * @param resourceName the string name of the desired resource
   * @param locale the locale of the current rebind permutation
   * @return a URL by which the resource can be loaded, <code>null</code> if one
   *         cannot be found
   */
  private static URL tryFindResource(Locator locator, String resourceName,
      String locale) {
    URL toReturn = null;

    // Look for locale-specific variants of individual resources
    if (locale != null) {
      // Convert language_country_variant to independent pieces
      String[] localeSegments = locale.split("_");
      int lastDot = resourceName.lastIndexOf(".");
      String prefix = lastDot == -1 ? resourceName : resourceName.substring(0,
          lastDot);
      String extension = lastDot == -1 ? "" : resourceName.substring(lastDot);

      for (int i = localeSegments.length - 1; i >= -1; i--) {
        String localeInsert = "";
        for (int j = 0; j <= i; j++) {
          localeInsert += "_" + localeSegments[j];
        }

        toReturn = locator.locate(prefix + localeInsert + extension);
        if (toReturn != null) {
          break;
        }
      }
    } else {
      toReturn = locator.locate(resourceName);
    }

    return toReturn;
  }

  /**
   * Performs the locale lookup function for a given resource name.  Will also
   * add the located resource to the requirements object for the context.
   *
   * @param locator the Locator to use to load the resources
   * @param context the ResourceContext
   * @param resourceName the string name of the desired resource
   * @param locale the locale of the current rebind permutation
   * @return a URL by which the resource can be loaded, <code>null</code> if one
   *         cannot be found
   */
  private static URL tryFindResource(Locator locator, ResourceContext context,
      String resourceName, String locale) {

    URL toReturn = tryFindResource(locator, resourceName, locale);
    if (toReturn != null && context != null) {
      ClientBundleRequirements reqs = context.getRequirements();
      if (reqs != null) {
        reqs.addResolvedResource(resourceName, toReturn);
      }
    }

    return toReturn;
  }

  /**
   * Utility class.
   */
  private ResourceGeneratorUtil() {
  }
}
