/*
 * 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.TreeLogger.Type;
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.EmittedArtifact.Visibility;
import com.google.gwt.core.ext.linker.LinkerOrder;
import com.google.gwt.core.ext.linker.LinkerOrder.Order;
import com.google.gwt.core.ext.linker.PublicResource;
import com.google.gwt.core.ext.linker.SelectionProperty;
import com.google.gwt.dev.cfg.BindingProperty;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.Script;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.JsOutputOption;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.js.JsLiteralInterner;
import com.google.gwt.dev.js.JsNamer.IllegalNameException;
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.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.JsFunction;
import com.google.gwt.dev.js.ast.JsModVisitor;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsScope;
import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.dev.util.DefaultTextOutput;
import com.google.gwt.dev.util.OutputFileSet;
import com.google.gwt.util.tools.Utility;

import java.io.BufferedOutputStream;
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 JsLiteralInterner} 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 ctx) {
      didChange |= JsLiteralInterner.exec(program, x.getBody(), x.getScope(), true);
      return false;
    }
  }

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

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

  private final SortedSet<ConfigurationProperty> configurationProperties;

  private final JsOutputOption outputOption;

  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 ResourceOracle publicResourceOracle;

  private final SortedSet<SelectionProperty> selectionProperties;

  public StandardLinkerContext(TreeLogger logger, ModuleDef module,
      ResourceOracle publicResourceOracle, JsOutputOption outputOption)
      throws UnableToCompleteException {
    logger = logger.branch(TreeLogger.DEBUG,
        "Constructing StandardLinkerContext", null);

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

    // 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();
      if (order == null) {
        logger.log(Type.ERROR, linkerClass.getName() + " has no @LinkerOrder annotation");
        throw new UnableToCompleteException();
      }
      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 (com.google.gwt.dev.cfg.ConfigurationProperty p : module
          .getProperties().getConfigurationProperties()) {
        StandardConfigurationProperty newProp = new StandardConfigurationProperty(p);
        mutableConfigurationProperties.add(newProp);
        if (logger.isLoggable(TreeLogger.SPAM)) {
          logger.log(TreeLogger.SPAM,
              "Added configuration property " + newProp, null);
        }
      }
      for (BindingProperty p : module.getProperties().getBindingProperties()) {
        StandardSelectionProperty newProp = new StandardSelectionProperty(p);
        mutableSelectionProperties.add(newProp);
        propertiesByName.put(newProp.getName(), newProp);
        if (logger.isLoggable(TreeLogger.SPAM)) {
          logger.log(TreeLogger.SPAM, "Added selection property " + newProp,
              null);
        }
      }
      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 : publicResourceOracle.getPathNames()) {
      String partialPath = path.replace(File.separatorChar, '/');
      PublicResource resource = new StandardPublicResource(partialPath,
          publicResourceOracle.getResource(path));
      artifacts.add(resource);
      if (logger.isLoggable(TreeLogger.SPAM)) {
        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++));
        if (logger.isLoggable(TreeLogger.SPAM)) {
          logger.log(TreeLogger.SPAM, "Added script " + url, null);
        }
      }
    }

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

  @Override
  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;
  }

  @Override
  public String getModuleFunctionName() {
    return moduleFunctionName;
  }

  @Override
  public long getModuleLastModified() {
    return moduleLastModified;
  }

  @Override
  public String getModuleName() {
    return moduleName;
  }

  @Override
  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;
  }

  @Override
  public boolean isOutputCompact() {
    return outputOption.shouldMinimize();
  }

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

  @Override
  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();
    topScope.declareUnobfuscatableName(getModuleFunctionName());

    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);

    try {
      switch (outputOption) {
        case OBFUSCATED:
          /*
           * We can't apply the regular JsLiteralInterner to the JsProgram that
           * we've just created. In the normal case, the JsLiteralInterner 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, null);
          break;
        case PRETTY:
          // We don't intern strings in pretty mode to improve readability
          JsPrettyNamer.exec(jsProgram, null);
          break;
        case DETAILED:
          TopFunctionStringInterner.exec(jsProgram);
          JsVerboseNamer.exec(jsProgram, null);
          break;
        default:
          throw new InternalCompilerException("Unknown output mode");
      }
    } catch (IllegalNameException e) {
      logger.log(TreeLogger.ERROR, e.getMessage(), e);
      throw new UnableToCompleteException();
    }

    DefaultTextOutput out = new DefaultTextOutput(outputOption.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 visibility the level of visibility of artifacts to output
   * @param out where to emit the artifact contents
   */
  public void produceOutput(TreeLogger logger, ArtifactSet artifacts,
      Visibility visibility, OutputFileSet out)
      throws UnableToCompleteException {
    logger = logger.branch(TreeLogger.TRACE, "Linking " + visibility
        + " 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.getVisibility().matches(visibility)) {
        continue;
      }

      String partialPath = artifact.getPartialPath();
      if (artifact.getVisibility() != Visibility.Public) {
        // Any non-public linker will have their artifacts stored in a directory
        // named after the linker.
        partialPath = getExtraPathForLinker(artifact.getLinker(), partialPath);
        if (partialPath.startsWith("/")) {
          partialPath = partialPath.substring(1);
        }
      }
      OutputStream artifactStream = null;
      try {
        artifactStream = new BufferedOutputStream(out.openForWrite(partialPath,
            artifact.getLastModified()));
        artifact.writeTo(artifactLogger, artifactStream);
      } catch (IOException e) {
        artifactLogger.log(TreeLogger.ERROR,
            "Fatal error emitting artifact: " + artifact.getPartialPath(), e);
        // Do not fail for Private artifacts, just log the error
        if (visibility != Visibility.Private) {
          throw new UnableToCompleteException();
        }
      } finally {
        Utility.close(artifactStream);
      }
    }
  }

  /**
   * (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();
      }
    }
  }
}
