/*
 * 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.dev.cfg;

import com.google.gwt.core.ext.Linker;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.LinkerOrder;
import com.google.gwt.core.ext.linker.LinkerOrder.Order;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.javac.CompilationProblemReporter;
import com.google.gwt.dev.javac.CompilationState;
import com.google.gwt.dev.javac.CompilationStateBuilder;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.dev.resource.impl.DefaultFilters;
import com.google.gwt.dev.resource.impl.PathPrefix;
import com.google.gwt.dev.resource.impl.PathPrefixSet;
import com.google.gwt.dev.resource.impl.ResourceFilter;
import com.google.gwt.dev.resource.impl.ResourceOracleImpl;
import com.google.gwt.dev.util.Empty;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.thirdparty.guava.common.base.Preconditions;
import com.google.gwt.thirdparty.guava.common.collect.Lists;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Represents a module specification. In principle, this could be built without
 * XML for unit tests.
 */
public class ModuleDef {

  /**
   * Marks a module in a way that can be used to calculate the effective bounds of a library module
   * in a module tree.
   */
  public enum ModuleType {
    /**
     * A module that acts as just a bundle of source code to be included in a referencing library.
     * The contained code may form circular references with other source within the contiguous chunk
     * of modules made up of a library and it's subtree of filesets. As a result a fileset can not
     * be compiled on it's own and must be compiled as part of a library.
     */
    FILESET,
    /**
     * The default type of module. Libraries should be independently compilable and are expected to
     * explicitly declare all of their immediate dependencies and include paths and none of their
     * contained source should be part of a circular reference with any source outside the effective
     * bounds of the library.
     */
    LIBRARY
  }

  /**
   * When walking a module tree of mixed library and fileset modules, attributes are accumulated and
   * stored. But when compiling separately, some attributes should only be collected from the
   * effective target module. AttributeSource is used to classify these "in target module" and "out
   * of target module" times.
   */
  private enum AttributeSource {
    EXTERNAL_LIBRARY, TARGET_LIBRARY
  }

  private static final ResourceFilter NON_JAVA_RESOURCES = new ResourceFilter() {
    @Override
    public boolean allows(String path) {
      return !path.endsWith(".java") && !path.endsWith(".class");
    }
  };

  private static final Comparator<Map.Entry<String, ?>> REV_NAME_CMP =
      new Comparator<Map.Entry<String, ?>>() {
        @Override
        public int compare(Map.Entry<String, ?> entry1, Map.Entry<String, ?> entry2) {
          String key1 = entry1.getKey();
          String key2 = entry2.getKey();
          // intentionally reversed
          return key2.compareTo(key1);
        }
      };

  public static boolean isValidModuleName(String moduleName) {
    // Check for an empty string between two periods.
    if (moduleName.contains("..")) {
      return false;
    }
    // Insure the package name components are a valid Java ident.
    String[] parts = moduleName.split("\\.");
    for (int i = 0; i < parts.length - 1; i++) {
      String part = parts[i];
      if (!Util.isValidJavaIdent(part)) {
        return false;
      }
    }
    return true;
  }

  private final Set<String> activeLinkers = new LinkedHashSet<String>();

  private String activePrimaryLinker;

  /**
   * A set of URLs for <module>.gwtar files found on the classpath that correspond
   * to <module>.gwt.xml files loaded as a part of this module's nested load.
   *
   * @see com.google.gwt.dev.CompileModule
   */
  private final List<URL> archiveURLs = new ArrayList<URL>();

  private boolean collapseAllProperties;

  private final DefaultFilters defaultFilters;

  private final List<String> entryPointTypeNames = new ArrayList<String>();

  private final Set<File> gwtXmlFiles = new HashSet<File>();

  private final Set<String> inheritedModules = new HashSet<String>();

  /**
   * All resources found on the public path, specified by <public> directives in
   * modules (or the implicit ./public directory). Marked 'lazy' because it does not
   * start searching for resources until a query is made.
   */
  private ResourceOracleImpl lazyPublicOracle;

  /**
   * A subset of lazySourceOracle, contains files other than .java and .class files.
   */
  private ResourceOracleImpl lazyResourcesOracle;

  /**
   * Contains all files from the source path, specified by <source> and <super>
   * directives in modules (or the implicit ./client directory).
   */
  private ResourceOracleImpl lazySourceOracle;

  private final Map<String, Class<? extends Linker>> linkerTypesByName =
      new LinkedHashMap<String, Class<? extends Linker>>();

  private final long moduleDefCreationTime = System.currentTimeMillis();

  /**
   * Whether the module tree is being considered to be one contiguous compilable whole as opposed to
   * a tree of independently compilable library modules.
   */
  private final boolean monolithic;

  private final String name;
  private final ResourceLoader resources;

  /**
   * Must use a separate field to track override, because setNameOverride() will
   * get called every time a module is inherited, but only the last one matters.
   */
  private String nameOverride;

  /**
   * Used to keep track of the current category of attribute source. When the attribute source is
   * TARGET_LIBRARY all attributes are accumulated but when it is EXTERNAL_LIBRARY there are some
   * attributes that are not collected.
   */
  private Deque<AttributeSource> currentAttributeSource = Lists.newLinkedList();

  private boolean needsRefresh;

  private final Properties properties = new Properties();

  private PathPrefixSet publicPrefixSet = new PathPrefixSet();

  private final Rules rules = new Rules();

  private final Scripts scripts = new Scripts();

  private final Map<String, String> servletClassNamesByPath = new HashMap<String, String>();

  private PathPrefixSet sourcePrefixSet = new PathPrefixSet();

  private final Styles styles = new Styles();

  public ModuleDef(String name) {
    this(name, ResourceLoaders.forClassLoader(Thread.currentThread()));
  }

  public ModuleDef(String name, ResourceLoader resources) {
    this(name, resources, true);
  }

  public ModuleDef(String name, ResourceLoader resources, boolean monolithic) {
    this.name = name;
    this.resources = resources;
    this.monolithic = monolithic;
    defaultFilters = new DefaultFilters();
  }

  public synchronized void addEntryPointTypeName(String typeName) {
    if (!attributeIsForTargetLibrary()) {
      return;
    }
    entryPointTypeNames.add(typeName);
  }

  public void addGwtXmlFile(File xmlFile) {
    gwtXmlFiles.add(xmlFile);
  }

  public void addLinker(String name) {
    Class<? extends Linker> clazz = getLinker(name);
    assert clazz != null;

    LinkerOrder order = clazz.getAnnotation(LinkerOrder.class);
    if (order.value() == Order.PRIMARY) {
      if (activePrimaryLinker != null) {
        activeLinkers.remove(activePrimaryLinker);
      }
      activePrimaryLinker = name;
    }

    activeLinkers.add(name);
  }

  public synchronized void addPublicPackage(String publicPackage, String[] includeList,
      String[] excludeList, String[] skipList, boolean defaultExcludes, boolean caseSensitive) {
    if (lazyPublicOracle != null) {
      throw new IllegalStateException("Already normalized");
    }
    if (!attributeIsForTargetLibrary()) {
      return;
    }
    publicPrefixSet.add(new PathPrefix(publicPackage, defaultFilters.customResourceFilter(
        includeList, excludeList, skipList, defaultExcludes, caseSensitive), true, excludeList));
  }

  public void addRule(Rule rule) {
    if (!attributeIsForTargetLibrary()) {
      return;
    }
    getRules().prepend(rule);
  }

  public void addSourcePackage(String sourcePackage, String[] includeList, String[] excludeList,
      String[] skipList, boolean defaultExcludes, boolean caseSensitive) {
    addSourcePackageImpl(sourcePackage, includeList, excludeList, skipList, defaultExcludes,
        caseSensitive, false);
  }

  public void addSourcePackageImpl(String sourcePackage, String[] includeList,
      String[] excludeList, String[] skipList, boolean defaultExcludes, boolean caseSensitive,
      boolean isSuperSource) {
    if (lazySourceOracle != null) {
      throw new IllegalStateException("Already normalized");
    }
    if (!attributeIsForTargetLibrary()) {
      return;
    }
    PathPrefix pathPrefix =
        new PathPrefix(sourcePackage, defaultFilters.customJavaFilter(includeList, excludeList,
            skipList, defaultExcludes, caseSensitive), isSuperSource, excludeList);
    sourcePrefixSet.add(pathPrefix);
  }

  public void addSuperSourcePackage(String superSourcePackage, String[] includeList,
      String[] excludeList, String[] skipList, boolean defaultExcludes, boolean caseSensitive) {
    addSourcePackageImpl(superSourcePackage, includeList, excludeList, skipList, defaultExcludes,
        caseSensitive, true);
  }

  /**
   * Free up memory no longer needed in later compile stages. After calling this
   * method, the ResourceOracle will be empty and unusable. Calling
   * {@link #refresh()} will restore them.
   */
  public synchronized void clear() {
    if (lazySourceOracle != null) {
      lazySourceOracle.clear();
    }
    rules.dispose();
  }

  public void clearEntryPoints() {
    entryPointTypeNames.clear();
  }

  /**
   * Associate a Linker class with a symbolic name. If the name had been
   * previously assigned, this method will redefine the name. If the redefined
   * linker had been previously added to the set of active linkers, the old
   * active linker will be replaced with the new linker.
   */
  public void defineLinker(TreeLogger logger, String name, Class<? extends Linker> linker)
      throws UnableToCompleteException {
    Class<? extends Linker> old = getLinker(name);
    if (old != null) {
      // Redefining an existing name
      if (activePrimaryLinker.equals(name)) {
        // Make sure the new one is also a primary linker
        if (!linker.getAnnotation(LinkerOrder.class).value().equals(Order.PRIMARY)) {
          logger.log(TreeLogger.ERROR, "Redefining primary linker " + name
              + " with non-primary implementation " + linker.getName());
          throw new UnableToCompleteException();
        }

      } else if (activeLinkers.contains(name)) {
        // Make sure it's a not a primary linker
        if (linker.getAnnotation(LinkerOrder.class).value().equals(Order.PRIMARY)) {
          logger.log(TreeLogger.ERROR, "Redefining non-primary linker " + name
              + " with primary implementation " + linker.getName());
          throw new UnableToCompleteException();
        }
      }
    }
    linkerTypesByName.put(name, linker);
  }

  /**
   * Called as module tree parsing enters and exits individual module file of various types and so
   * provides the ModuleDef with an opportunity to keep track of what context it is currently
   * operating.<br />
   *
   * At the moment the ModuleDef uses it's monolithic property in combination with the entering
   * modules ModuleType to updates its idea of attribute source.
   */
  public void enterModule(ModuleType moduleType) {
    if (monolithic) {
      // When you're monolithic the module tree is all effectively one giant library.
      currentAttributeSource.push(AttributeSource.TARGET_LIBRARY);
      return;
    }

    // When compiling separately it's not legal to have a fileset module at the root.
    Preconditions.checkArgument(
        !(currentAttributeSource.isEmpty() && moduleType == ModuleType.FILESET));

    // The compilation target always starts at the root of the graph so if there is a library type
    // module at the root of the graph.
    if (currentAttributeSource.isEmpty() && moduleType == ModuleType.LIBRARY) {
      // Then any attributes you see are your own.
      currentAttributeSource.push(AttributeSource.TARGET_LIBRARY);
      return;
    }

    // If at the moment any attributes you see are your own.
    if (currentAttributeSource.peek() == AttributeSource.TARGET_LIBRARY) {
      // And you enter a fileset module
      if (moduleType == ModuleType.FILESET) {
        // Then any attributes you see are still your own.
        currentAttributeSource.push(AttributeSource.TARGET_LIBRARY);
      } else {
        // But if you enter a library module then any attributes you see are external.
        currentAttributeSource.push(AttributeSource.EXTERNAL_LIBRARY);
      }
    } else if (currentAttributeSource.peek() == AttributeSource.EXTERNAL_LIBRARY) {
      // If your current attribute source is an external library then regardless of whether you
      // enter another fileset or library your attribute source is still external.
      currentAttributeSource.push(AttributeSource.EXTERNAL_LIBRARY);
    }
  }

  public void exitModule() {
    currentAttributeSource.pop();
  }

  public synchronized Resource findPublicFile(String partialPath) {
    doRefresh();
    return lazyPublicOracle.getResourceMap().get(partialPath);
  }

  public synchronized String findServletForPath(String actual) {
    // Walk in backwards sorted order to find the longest path match first.
    Set<Entry<String, String>> entrySet = servletClassNamesByPath.entrySet();
    Entry<String, String>[] entries = Util.toArray(Entry.class, entrySet);
    Arrays.sort(entries, REV_NAME_CMP);
    for (int i = 0, n = entries.length; i < n; ++i) {
      String mapping = entries[i].getKey();
      /*
       * Ensure that URLs that match the servlet mapping, including those that
       * have additional path_info, get routed to the correct servlet.
       *
       * See "Inside Servlets", Second Edition, pg. 208
       */
      if (actual.equals(mapping) || actual.startsWith(mapping + "/")) {
        return entries[i].getValue();
      }
    }
    return null;
  }

  /**
   * Returns the Resource for a source file if it is found; <code>null</code>
   * otherwise.
   *
   * @param partialPath the partial path of the source file
   * @return the resource for the requested source file
   */
  public synchronized Resource findSourceFile(String partialPath) {
    doRefresh();
    return lazySourceOracle.getResourceMap().get(partialPath);
  }

  public Set<String> getActiveLinkerNames() {
    return new LinkedHashSet<String>(activeLinkers);
  }

  public Set<Class<? extends Linker>> getActiveLinkers() {
    Set<Class<? extends Linker>> toReturn = new LinkedHashSet<Class<? extends Linker>>();
    for (String linker : activeLinkers) {
      assert linkerTypesByName.containsKey(linker) : linker;
      toReturn.add(linkerTypesByName.get(linker));
    }
    return toReturn;
  }

  public Class<? extends Linker> getActivePrimaryLinker() {
    assert linkerTypesByName.containsKey(activePrimaryLinker) : activePrimaryLinker;
    return linkerTypesByName.get(activePrimaryLinker);
  }

  /**
   * Returns URLs to fetch archives of precompiled compilation units.
   *
   * @see com.google.gwt.dev.CompileModule
   */
  public Collection<URL> getAllCompilationUnitArchiveURLs() {
    return Collections.unmodifiableCollection(archiveURLs);
  }

  public String[] getAllPublicFiles() {
    doRefresh();
    return lazyPublicOracle.getPathNames().toArray(Empty.STRINGS);
  }

  /**
   * Strictly for statistics gathering. There is no guarantee that the source
   * oracle has been initialized.
   */
  public String[] getAllSourceFiles() {
    doRefresh();
    return lazySourceOracle.getPathNames().toArray(Empty.STRINGS);
  }

  /**
   * Returns the physical name for the module by which it can be found in the
   * classpath.
   */
  public String getCanonicalName() {
    return name;
  }

  public CompilationState getCompilationState(TreeLogger logger, CompilerContext compilerContext)
      throws UnableToCompleteException {
    doRefresh();
    CompilationState compilationState =
        CompilationStateBuilder.buildFrom(logger, compilerContext, lazySourceOracle.getResources());
    checkForSeedTypes(logger, compilationState);
    return compilationState;
  }

  public synchronized String[] getEntryPointTypeNames() {
    final int n = entryPointTypeNames.size();
    return entryPointTypeNames.toArray(new String[n]);
  }

  public synchronized String getFunctionName() {
    return getName().replace('.', '_');
  }

  public Class<? extends Linker> getLinker(String name) {
    return linkerTypesByName.get(name);
  }

  public Map<String, Class<? extends Linker>> getLinkers() {
    return linkerTypesByName;
  }

  public synchronized String getName() {
    return nameOverride != null ? nameOverride : name;
  }

  /**
   * The properties that have been defined.
   */
  public synchronized Properties getProperties() {
    return properties;
  }

  public synchronized ResourceOracle getResourcesOracle() {
    if (lazyResourcesOracle == null) {
      lazyResourcesOracle = new ResourceOracleImpl(TreeLogger.NULL, resources);
      PathPrefixSet pathPrefixes = lazySourceOracle.getPathPrefixes();
      PathPrefixSet newPathPrefixes = new PathPrefixSet();
      for (PathPrefix pathPrefix : pathPrefixes.values()) {
        newPathPrefixes.add(new PathPrefix(pathPrefix.getPrefix(), NON_JAVA_RESOURCES, pathPrefix
            .shouldReroot()));
      }
      lazyResourcesOracle.setPathPrefixes(newPathPrefixes);
      ResourceOracleImpl.refresh(TreeLogger.NULL, lazyResourcesOracle);
    } else {
      doRefresh();
    }
    return lazyResourcesOracle;
  }

  /**
   * Gets a reference to the internal rules for this module def.
   */
  public synchronized Rules getRules() {
    return rules;
  }

  /**
   * Gets a reference to the internal scripts list for this module def.
   */
  public Scripts getScripts() {
    return scripts;
  }

  public synchronized String[] getServletPaths() {
    return servletClassNamesByPath.keySet().toArray(Empty.STRINGS);
  }

  /**
   * Gets a reference to the internal styles list for this module def.
   */
  public Styles getStyles() {
    return styles;
  }

  public boolean isGwtXmlFileStale() {
    return lastModified() > moduleDefCreationTime;
  }

  public boolean isInherited(String moduleName) {
    return inheritedModules.contains(moduleName);
  }

  public long lastModified() {
    long lastModified = 0;
    for (File xmlFile : gwtXmlFiles) {
      if (xmlFile.exists()) {
        lastModified = Math.max(lastModified, xmlFile.lastModified());
      }
    }
    return lastModified > 0 ? lastModified : moduleDefCreationTime;
  }

  /**
   * For convenience in unit tests, servlets can be automatically loaded and
   * mapped in the embedded web server. If a servlet is already mapped to the
   * specified path, it is replaced.
   *
   * @param path the url path at which the servlet resides
   * @param servletClassName the name of the servlet to publish
   */
  public synchronized void mapServlet(String path, String servletClassName) {
    servletClassNamesByPath.put(path, servletClassName);
  }

  public synchronized void refresh() {
    needsRefresh = true;
  }

  /**
   * Mainly for testing and decreasing compile times.
   */
  public void setCollapseAllProperties(boolean collapse) {
    collapseAllProperties = collapse;
  }

  /**
   * Override the module's apparent name. Setting this value to
   * <code>null<code> will disable the name override.
   */
  public synchronized void setNameOverride(String nameOverride) {
    this.nameOverride = nameOverride;
  }

  void addCompilationUnitArchiveURL(URL url) {
    archiveURLs.add(url);
  }

  void addInteritedModule(String moduleName) {
    inheritedModules.add(moduleName);
  }

  /**
   * The final method to call when everything is setup. Before calling this
   * method, several of the getter methods may not be called. After calling this
   * method, the add methods may not be called.
   *
   * @param logger Logs the activity.
   */
  synchronized void normalize(TreeLogger logger) {
    Event moduleDefNormalize =
        SpeedTracerLogger.start(CompilerEventType.MODULE_DEF, "phase", "normalize");
    // Normalize property providers.
    //
    for (Property current : getProperties()) {
      if (current instanceof BindingProperty) {
        BindingProperty prop = (BindingProperty) current;

        if (collapseAllProperties) {
          prop.addCollapsedValues("*");
        }

        prop.normalizeCollapsedValues();

        /*
         * Create a default property provider for any properties with more than
         * one possible value and no existing provider.
         */
        if (prop.getProvider() == null && prop.getConstrainedValue() == null) {
          String src = "{";
          src += "return __gwt_getMetaProperty(\"";
          src += prop.getName();
          src += "\"); }";
          prop.setProvider(new PropertyProvider(src));
        }
      }
    }

    // Create the public path.
    TreeLogger branch = Messages.PUBLIC_PATH_LOCATIONS.branch(logger, null);
    lazyPublicOracle = new ResourceOracleImpl(branch, resources);
    lazyPublicOracle.setPathPrefixes(publicPrefixSet);

    // Create the source path.
    branch = Messages.SOURCE_PATH_LOCATIONS.branch(logger, null);
    lazySourceOracle = new ResourceOracleImpl(branch, resources);
    lazySourceOracle.setPathPrefixes(sourcePrefixSet);

    needsRefresh = true;
    moduleDefNormalize.end();
  }

  private void checkForSeedTypes(TreeLogger logger, CompilationState compilationState)
      throws UnableToCompleteException {
    // Sanity check the seed types and don't even start it they're missing.
    boolean seedTypesMissing = false;
    TypeOracle typeOracle = compilationState.getTypeOracle();
    if (typeOracle.findType("java.lang.Object") == null) {
      CompilationProblemReporter.logMissingTypeErrorWithHints(logger, "java.lang.Object",
          compilationState);
      seedTypesMissing = true;
    } else {
      TreeLogger branch = logger.branch(TreeLogger.TRACE, "Finding entry point classes", null);
      String[] typeNames = getEntryPointTypeNames();
      for (int i = 0; i < typeNames.length; i++) {
        String typeName = typeNames[i];
        if (typeOracle.findType(typeName) == null) {
          CompilationProblemReporter.logMissingTypeErrorWithHints(branch, typeName,
              compilationState);
          seedTypesMissing = true;
        }
      }
    }

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

  private synchronized void doRefresh() {
    if (!needsRefresh) {
      return;
    }
    Event moduleDefEvent =
        SpeedTracerLogger.start(CompilerEventType.MODULE_DEF, "phase", "refresh", "module",
            getName());
    // Refresh resource oracles.
    if (lazyResourcesOracle == null) {
      ResourceOracleImpl.refresh(TreeLogger.NULL, lazyPublicOracle, lazySourceOracle);
    } else {
      ResourceOracleImpl.refresh(TreeLogger.NULL, lazyPublicOracle, lazySourceOracle,
          lazyResourcesOracle);
    }
    moduleDefEvent.end();
    needsRefresh = false;
  }

  private boolean attributeIsForTargetLibrary() {
    return currentAttributeSource.isEmpty()
        || currentAttributeSource.peek() == AttributeSource.TARGET_LIBRARY;
  }
}
