/*
 * 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.impl.ResourceGeneratorUtilImpl;
import com.google.gwt.core.ext.impl.ResourceLocatorImpl;
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.ResourceOracle;
import com.google.gwt.resources.client.ClientBundle.Source;

import java.io.File;
import java.io.IOException;
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;

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

  /**
   * A locator that uses ResourceLocatorImpl to locate resources either in the ResourceOracle or the
   * ClassLoader.
   */
  private static class GeneralLocator implements Locator {
    private final ResourceOracle resourceOracle;
    private final TreeLogger logger;

    public GeneralLocator(TreeLogger logger, ResourceOracle resourceOracle) {
      this.logger = logger;
      this.resourceOracle = resourceOracle;
    }

    @Override
    public URL locate(String resourceName) {
      return ResourceLocatorImpl.tryFindResourceUrl(logger, resourceOracle, 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() {
    }

    @Override
    public URL locate(String resourceName) {
      File f = ResourceGeneratorUtilImpl.getGeneratedFile(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);
  }

  /**
   * 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
   */
  // TODO(stalcup): the addNamedFile() and Locator system are redundant and need to be deleted. They
  // exist because resources generated via the GeneratorContext are not queryable via the available
  // ResourceOracle. This should be corrected.
  public static void addNamedFile(String resourceName, File file) {
    // User code should not refer to private Compiler classes, but it is being done here in lieu of
    // the above mentioned refactoring.
    ResourceGeneratorUtilImpl.addGeneratedFile(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>
   * 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(logger, context.getGeneratorContext());
    URL[] toReturn = findResources(logger, locators, context, method,
        defaultSuffixes);
    return toReturn;
  }

  /**
   * Returns the most recent value of the <code>last-modified</code> header fields of all the Urls
   * in the <code>resources</code> array.
   * The result is the number of milliseconds since January 1, 1970 GMT.
   *
   * Returns 0 if the <code>last-modified</code> header field of one of the resources cannot
   * be determined.
   *
   * @return  the most recent modification date of the resources present in
   *          <code>resources</code> or 0 if not known.
   */
  public static long getLastModified(URL[] resources, TreeLogger logger) {
    long lastModificationDate = 0;
    for (URL url : resources) {
      long lastModified = 0;
      try {
        lastModified = url.openConnection().getLastModified();
      } catch (IOException e) {
        // Non-fatal, assuming we can re-open the stream later
        logger.log(TreeLogger.DEBUG, "Could not determine cached time", e);
      }
      if (lastModified == 0) {
        // either we cannot open the stream either the last modification date is not known
        return 0;
      } else {
        lastModificationDate = Math.max(lastModificationDate, lastModified);
      }
    }

    return lastModificationDate;
  }

  /**
   * 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(logger, 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 ClassLoader.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.
   *
   * @return an ordered array of Locator[]
   */
  private static Locator[] getDefaultLocators(TreeLogger logger, GeneratorContext genContext) {
    return new Locator[] {
        NamedFileLocator.INSTANCE, new GeneralLocator(logger, genContext.getResourcesOracle())};
  }

  /**
   * Get the current locale string.
   *
   * @param logger
   * @param genContext
   * @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 (context != null) {
      ClientBundleRequirements reqs = context.getRequirements();
      if (reqs != null) {
        reqs.addResolvedResource(resourceName, toReturn);
      }
    }

    return toReturn;
  }

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