/*
 * 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.core.ext.linker.impl;

import com.google.gwt.core.ext.Linker;
import com.google.gwt.core.ext.LinkerContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.ConfigurationProperty;
import com.google.gwt.core.ext.linker.EmittedArtifact;
import com.google.gwt.core.ext.linker.LinkerOrder;
import com.google.gwt.core.ext.linker.PublicResource;
import com.google.gwt.core.ext.linker.SelectionProperty;
import com.google.gwt.core.ext.linker.LinkerOrder.Order;
import com.google.gwt.dev.cfg.BindingProperty;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.Property;
import com.google.gwt.dev.cfg.Script;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.JJSOptions;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.js.JsObfuscateNamer;
import com.google.gwt.dev.js.JsParser;
import com.google.gwt.dev.js.JsParserException;
import com.google.gwt.dev.js.JsPrettyNamer;
import com.google.gwt.dev.js.JsSourceGenerationVisitor;
import com.google.gwt.dev.js.JsStringInterner;
import com.google.gwt.dev.js.JsSymbolResolver;
import com.google.gwt.dev.js.JsUnusedFunctionRemover;
import com.google.gwt.dev.js.JsVerboseNamer;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsModVisitor;
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsScope;
import com.google.gwt.dev.util.DefaultTextOutput;
import com.google.gwt.dev.util.OutputFileSet;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * An implementation of {@link LinkerContext} that is initialized from a
 * {@link ModuleDef}.
 */
public class StandardLinkerContext extends Linker implements LinkerContext {

  /**
   * Applies the {@link JsStringInterner} optimization to each top-level
   * function defined within a JsProgram.
   */
  private static class TopFunctionStringInterner extends JsModVisitor {

    public static boolean exec(JsProgram program) {
      TopFunctionStringInterner v = new TopFunctionStringInterner(program);
      v.accept(program);
      return v.didChange();
    }

    private final JsProgram program;

    public TopFunctionStringInterner(JsProgram program) {
      this.program = program;
    }

    @Override
    public boolean visit(JsFunction x, JsContext<JsExpression> ctx) {
      didChange |= JsStringInterner.exec(program, x.getBody(), x.getScope());
      return false;
    }
  }

  static final Comparator<ConfigurationProperty> CONFIGURATION_PROPERTY_COMPARATOR = new Comparator<ConfigurationProperty>() {
    public int compare(ConfigurationProperty o1, ConfigurationProperty o2) {
      return o1.getName().compareTo(o2.getName());
    }
  };

  static final Comparator<SelectionProperty> SELECTION_PROPERTY_COMPARATOR = new Comparator<SelectionProperty>() {
    public int compare(SelectionProperty o1, SelectionProperty o2) {
      return o1.getName().compareTo(o2.getName());
    }
  };

  private final SortedSet<ConfigurationProperty> configurationProperties;

  private final JJSOptions jjsOptions;

  private final List<Class<? extends Linker>> linkerClasses;
  private Linker[] linkers;
  private final Map<Class<? extends Linker>, String> linkerShortNames = new HashMap<Class<? extends Linker>, String>();
  private final String moduleFunctionName;
  private final long moduleLastModified;
  private final String moduleName;

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

  private final SortedSet<SelectionProperty> selectionProperties;

  public StandardLinkerContext(TreeLogger logger, ModuleDef module,
      JJSOptions jjsOptions) throws UnableToCompleteException {
    logger = logger.branch(TreeLogger.DEBUG,
        "Constructing StandardLinkerContext", null);

    this.jjsOptions = jjsOptions;
    this.moduleFunctionName = module.getFunctionName();
    this.moduleName = module.getName();
    this.moduleLastModified = module.lastModified();

    // Sort the linkers into the order they should actually run.
    linkerClasses = new ArrayList<Class<? extends Linker>>();

    // Get all the pre-linkers first.
    for (Class<? extends Linker> linkerClass : module.getActiveLinkers()) {
      Order order = linkerClass.getAnnotation(LinkerOrder.class).value();
      assert (order != null);
      if (order == Order.PRE) {
        linkerClasses.add(linkerClass);
      }
    }

    // Get the primary linker.
    Class<? extends Linker> primary = module.getActivePrimaryLinker();
    if (primary == null) {
      logger.log(
          TreeLogger.ERROR,
          "Primary linker is null.  Does your module "
              + "inherit from com.google.gwt.core.Core or com.google.gwt.user.User?");
    } else {
      linkerClasses.add(module.getActivePrimaryLinker());
    }

    // Get all the post-linkers IN REVERSE ORDER.
    {
      List<Class<? extends Linker>> postLinkerClasses = new ArrayList<Class<? extends Linker>>();
      for (Class<? extends Linker> linkerClass : module.getActiveLinkers()) {
        Order order = linkerClass.getAnnotation(LinkerOrder.class).value();
        assert (order != null);
        if (order == Order.POST) {
          postLinkerClasses.add(linkerClass);
        }
      }
      Collections.reverse(postLinkerClasses);
      linkerClasses.addAll(postLinkerClasses);
    }

    resetLinkers(logger);

    for (Map.Entry<String, Class<? extends Linker>> entry : module.getLinkers().entrySet()) {
      linkerShortNames.put(entry.getValue(), entry.getKey());
    }

    /*
     * This will make all private PublicResources and GeneratedResources appear
     * in the root of the module auxiliary directory.
     */
    linkerShortNames.put(this.getClass(), "");

    // Break ModuleDef properties out into LinkerContext interfaces
    {
      SortedSet<ConfigurationProperty> mutableConfigurationProperties = new TreeSet<ConfigurationProperty>(
          CONFIGURATION_PROPERTY_COMPARATOR);
      SortedSet<SelectionProperty> mutableSelectionProperties = new TreeSet<SelectionProperty>(
          SELECTION_PROPERTY_COMPARATOR);
      for (Property p : module.getProperties()) {
        // Create a new view
        if (p instanceof com.google.gwt.dev.cfg.ConfigurationProperty) {
          StandardConfigurationProperty newProp = new StandardConfigurationProperty(
              (com.google.gwt.dev.cfg.ConfigurationProperty) p);
          mutableConfigurationProperties.add(newProp);
          logger.log(TreeLogger.SPAM,
              "Added configuration property " + newProp, null);
        } else if (p instanceof BindingProperty) {
          StandardSelectionProperty newProp = new StandardSelectionProperty(
              (BindingProperty) p);
          mutableSelectionProperties.add(newProp);
          propertiesByName.put(newProp.getName(), newProp);
          logger.log(TreeLogger.SPAM, "Added selection property " + newProp,
              null);
        } else {
          logger.log(TreeLogger.ERROR, "Unknown property type "
              + p.getClass().getName());
        }
      }
      selectionProperties = Collections.unmodifiableSortedSet(mutableSelectionProperties);
      configurationProperties = Collections.unmodifiableSortedSet(mutableConfigurationProperties);
    }
  }

  public boolean allLinkersAreShardable() {
    return findUnshardableLinkers().isEmpty();
  }

  /**
   * Find all linkers that are not updated to support running generators on
   * compilations shards.
   */
  public List<Linker> findUnshardableLinkers() {
    List<Linker> problemLinkers = new ArrayList<Linker>();

    for (Linker linker : linkers) {
      if (!linker.isShardable()) {
        problemLinkers.add(linker);
      }
    }
    return problemLinkers;
  }

  /**
   * Convert all static resources in the specified module to artifacts.
   */
  public ArtifactSet getArtifactsForPublicResources(TreeLogger logger,
      ModuleDef module) {
    ArtifactSet artifacts = new ArtifactSet();
    for (String path : module.getAllPublicFiles()) {
      String partialPath = path.replace(File.separatorChar, '/');
      PublicResource resource = new StandardPublicResource(partialPath,
          module.findPublicFile(path));
      artifacts.add(resource);
      logger.log(TreeLogger.SPAM, "Added public resource " + resource, null);
    }

    {
      int index = 0;
      for (Script script : module.getScripts()) {
        String url = script.getSrc();
        artifacts.add(new StandardScriptReference(url, index++));
        logger.log(TreeLogger.SPAM, "Added script " + url, null);
      }
    }

    {
      int index = 0;
      for (String style : module.getStyles()) {
        artifacts.add(new StandardStylesheetReference(style, index++));
        logger.log(TreeLogger.SPAM, "Added style " + style, null);
      }
    }
    return artifacts;
  }

  public SortedSet<ConfigurationProperty> getConfigurationProperties() {
    return configurationProperties;
  }

  @Override
  public String getDescription() {
    return "Root Linker";
  }

  /**
   * Return the full path for an artifact produced by <code>linkertype</code>
   * that has the specified partial path. The full path will be the linker's
   * short name, as defined in the module file, followed by the given partial
   * path.
   */
  public String getExtraPathForLinker(Class<? extends Linker> linkerType,
      String partialPath) {
    assert linkerShortNames.containsKey(linkerType) : linkerType.getName()
        + " unknown";
    return linkerShortNames.get(linkerType) + '/' + partialPath;
  }

  public String getModuleFunctionName() {
    return moduleFunctionName;
  }

  public long getModuleLastModified() {
    return moduleLastModified;
  }

  public String getModuleName() {
    return moduleName;
  }

  public SortedSet<SelectionProperty> getProperties() {
    return selectionProperties;
  }

  public StandardSelectionProperty getProperty(String name) {
    return propertiesByName.get(name);
  }

  public ArtifactSet invokeFinalLink(TreeLogger logger, ArtifactSet artifacts)
      throws UnableToCompleteException {
    for (Linker linker : linkers) {
      if (linker.isShardable()) {
        TreeLogger linkerLogger = logger.branch(TreeLogger.TRACE,
            "Invoking Linker " + linker.getDescription(), null);
        artifacts = linker.link(linkerLogger, this, artifacts, false);
      }
    }
    return artifacts;
  }

  /**
   * Run linkers that have not been updated for the shardable API.
   */
  public ArtifactSet invokeLegacyLinkers(TreeLogger logger,
      ArtifactSet artifacts) throws UnableToCompleteException {
    ArtifactSet workingArtifacts = new ArtifactSet(artifacts);

    for (Linker linker : linkers) {
      if (!linker.isShardable()) {
        TreeLogger linkerLogger = logger.branch(TreeLogger.TRACE,
            "Invoking Linker " + linker.getDescription(), null);
        workingArtifacts.freeze();
        try {
          workingArtifacts = linker.link(linkerLogger, this, workingArtifacts);
        } catch (Throwable e) {
          linkerLogger.log(TreeLogger.ERROR, "Failed to link", e);
          throw new UnableToCompleteException();
        }
      }
    }
    return workingArtifacts;
  }

  /**
   * Invoke the shardable linkers on one permutation result. Those linkers run
   * with the precompile artifacts as input.
   */
  public ArtifactSet invokeLinkForOnePermutation(TreeLogger logger,
      StandardCompilationResult permResult, ArtifactSet permArtifacts)
      throws UnableToCompleteException {
    ArtifactSet workingArtifacts = new ArtifactSet(permArtifacts);
    workingArtifacts.add(permResult);

    for (Linker linker : linkers) {
      if (linker.isShardable()) {
        TreeLogger linkerLogger = logger.branch(TreeLogger.TRACE,
            "Invoking Linker " + linker.getDescription(), null);
        try {
          workingArtifacts.freeze();
          workingArtifacts = linker.link(logger, this, workingArtifacts, true);
        } catch (Throwable e) {
          linkerLogger.log(TreeLogger.ERROR, "Failed to link", e);
          throw new UnableToCompleteException();
        }
      }
    }

    /*
     * Reset linkers so that they don't accidentally carry any state across
     * permutations
     */
    resetLinkers(logger);

    workingArtifacts.freeze();
    return workingArtifacts;
  }

  public ArtifactSet invokeRelink(TreeLogger logger,
      ArtifactSet newlyGeneratedArtifacts) throws UnableToCompleteException {
    ArtifactSet workingArtifacts = new ArtifactSet(newlyGeneratedArtifacts);

    for (Linker linker : linkers) {
      TreeLogger linkerLogger = logger.branch(TreeLogger.TRACE,
          "Invoking relink on Linker " + linker.getDescription(), null);
      workingArtifacts.freeze();
      try {
        workingArtifacts = linker.relink(linkerLogger, this, workingArtifacts);
      } catch (Throwable e) {
        linkerLogger.log(TreeLogger.ERROR, "Failed to relink", e);
        throw new UnableToCompleteException();
      }
    }
    return workingArtifacts;
  }

  public boolean isOutputCompact() {
    return jjsOptions.getOutput().shouldMinimize();
  }

  @Override
  public ArtifactSet link(TreeLogger logger, LinkerContext context,
      ArtifactSet artifacts) {
    throw new UnsupportedOperationException();
  }

  public String optimizeJavaScript(TreeLogger logger, String program)
      throws UnableToCompleteException {
    logger = logger.branch(TreeLogger.DEBUG, "Attempting to optimize JS", null);
    Reader r = new StringReader(program);
    JsProgram jsProgram = new JsProgram();
    JsScope topScope = jsProgram.getScope();
    JsName funcName = topScope.declareName(getModuleFunctionName());
    funcName.setObfuscatable(false);

    try {
      SourceInfo sourceInfo = jsProgram.createSourceInfo(1,
          "StandardLinkerContext.optimizeJavaScript");
      JsParser.parseInto(sourceInfo, topScope, jsProgram.getGlobalBlock(), r);
    } catch (IOException e) {
      throw new RuntimeException("Unexpected error reading in-memory stream", e);
    } catch (JsParserException e) {
      logger.log(TreeLogger.ERROR, "Unable to parse JavaScript", e);
      throw new UnableToCompleteException();
    }

    JsSymbolResolver.exec(jsProgram);
    JsUnusedFunctionRemover.exec(jsProgram);

    switch (jjsOptions.getOutput()) {
      case OBFUSCATED:
        /*
         * We can't apply the regular JsStringInterner to the JsProgram that
         * we've just created. In the normal case, the JsStringInterner adds an
         * additional statement to the program's global JsBlock, however we
         * don't know exactly what the form and structure of our JsProgram are,
         * so we'll limit the scope of the modifications to each top-level
         * function within the program.
         */
        TopFunctionStringInterner.exec(jsProgram);
        JsObfuscateNamer.exec(jsProgram);
        break;
      case PRETTY:
        // We don't intern strings in pretty mode to improve readability
        JsPrettyNamer.exec(jsProgram);
        break;
      case DETAILED:
        // As above with OBFUSCATED
        TopFunctionStringInterner.exec(jsProgram);
        JsVerboseNamer.exec(jsProgram);
        break;
      default:
        throw new InternalCompilerException("Unknown output mode");
    }

    DefaultTextOutput out = new DefaultTextOutput(
        jjsOptions.getOutput().shouldMinimize());
    JsSourceGenerationVisitor v = new JsSourceGenerationVisitor(out);
    v.accept(jsProgram);
    return out.toString();
  }

  /**
   * Emit EmittedArtifacts artifacts onto <code>out</code>. Does not close
   * <code>out</code>.
   * 
   * @param logger where to log progress
   * @param artifacts the artifacts to emit
   * @param emitPrivates whether to emit the private artifacts only, vs. the
   *          public artifacts only
   * @param out where to emit the artifact contents
   */
  public void produceOutput(TreeLogger logger, ArtifactSet artifacts,
      boolean emitPrivates, OutputFileSet out) throws UnableToCompleteException {
    String publicness = emitPrivates ? "private" : "public";
    logger = logger.branch(TreeLogger.TRACE, "Linking " + publicness
        + " artifacts into " + out.getPathDescription(), null);

    for (EmittedArtifact artifact : artifacts.find(EmittedArtifact.class)) {
      TreeLogger artifactLogger = logger.branch(TreeLogger.DEBUG,
          "Emitting resource " + artifact.getPartialPath(), null);

      if (artifact.isPrivate() != emitPrivates) {
        continue;
      }

      String partialPath = artifact.getPartialPath();
      if (artifact.isPrivate()) {
        partialPath = getExtraPathForLinker(artifact.getLinker(), partialPath);
        if (partialPath.startsWith("/")) {
          partialPath = partialPath.substring(1);
        }
      }
      try {
        OutputStream artifactStream = out.openForWrite(partialPath,
            artifact.getLastModified());
        artifact.writeTo(artifactLogger, artifactStream);
        artifactStream.close();
      } catch (IOException e) {
        artifactLogger.log(TreeLogger.ERROR,
            "Fatal error emitting this artifact", e);
      }
    }
  }

  /**
   * (Re)instantiate all linkers.
   */
  private void resetLinkers(TreeLogger logger) throws UnableToCompleteException {
    linkers = new Linker[linkerClasses.size()];
    int i = 0;
    for (Class<? extends Linker> linkerClass : linkerClasses) {
      try {
        linkers[i++] = linkerClass.newInstance();
      } catch (InstantiationException e) {
        logger.log(TreeLogger.ERROR, "Unable to create Linker", e);
        throw new UnableToCompleteException();
      } catch (IllegalAccessException e) {
        logger.log(TreeLogger.ERROR, "Unable to create Linker", e);
        throw new UnableToCompleteException();
      }
    }
  }
}
