/*
 * 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;

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.Artifact;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.EmittedArtifact;
import com.google.gwt.core.ext.linker.SelectionProperty;
import com.google.gwt.core.ext.linker.impl.BinaryOnlyArtifactWrapper;
import com.google.gwt.core.ext.linker.impl.JarEntryEmittedArtifact;
import com.google.gwt.core.ext.linker.impl.StandardCompilationResult;
import com.google.gwt.core.ext.linker.impl.StandardLinkerContext;
import com.google.gwt.dev.CompileTaskRunner.CompileTask;
import com.google.gwt.dev.Precompile.PrecompileOptions;
import com.google.gwt.dev.cfg.BindingProperty;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.ModuleDefLoader;
import com.google.gwt.dev.cfg.PropertyPermutations;
import com.google.gwt.dev.cfg.StaticPropertyOracle;
import com.google.gwt.dev.jjs.JJSOptions;
import com.google.gwt.dev.jjs.PermutationResult;
import com.google.gwt.dev.jjs.impl.CodeSplitter;
import com.google.gwt.dev.util.FileBackedObject;
import com.google.gwt.dev.util.NullOutputFileSet;
import com.google.gwt.dev.util.OutputFileSet;
import com.google.gwt.dev.util.OutputFileSetOnDirectory;
import com.google.gwt.dev.util.OutputFileSetOnJar;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.arg.ArgHandlerExtraDir;
import com.google.gwt.dev.util.arg.ArgHandlerWarDir;
import com.google.gwt.dev.util.arg.OptionExtraDir;
import com.google.gwt.dev.util.arg.OptionOutDir;
import com.google.gwt.dev.util.arg.OptionWarDir;
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 java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;

/**
 * Performs the last phase of compilation, merging the compilation outputs.
 */
public class Link {
  /**
   * Options for Link.
   */
  @Deprecated
  public interface LegacyLinkOptions extends CompileTaskOptions, OptionOutDir {
  }

  /**
   * Options for Link.
   */
  public interface LinkOptions extends CompileTaskOptions, OptionExtraDir,
      OptionWarDir, LegacyLinkOptions {
  }

  static class ArgProcessor extends CompileArgProcessor {
    @SuppressWarnings("deprecation")
    public ArgProcessor(LinkOptions options) {
      super(options);
      registerHandler(new ArgHandlerExtraDir(options));
      registerHandler(new ArgHandlerWarDir(options));
      registerHandler(new ArgHandlerOutDirDeprecated(options));
    }

    @Override
    protected String getName() {
      return Link.class.getName();
    }
  }

  /**
   * Concrete class to implement link options.
   */
  static class LinkOptionsImpl extends CompileTaskOptionsImpl implements
      LinkOptions {

    private File extraDir;
    private File outDir;
    private File warDir;

    public LinkOptionsImpl() {
    }

    public LinkOptionsImpl(LinkOptions other) {
      copyFrom(other);
    }

    public void copyFrom(LinkOptions other) {
      super.copyFrom(other);
      setExtraDir(other.getExtraDir());
      setWarDir(other.getWarDir());
      setOutDir(other.getOutDir());
    }

    public File getExtraDir() {
      return extraDir;
    }

    @Deprecated
    public File getOutDir() {
      return outDir;
    }

    public File getWarDir() {
      return warDir;
    }

    public void setExtraDir(File extraDir) {
      this.extraDir = extraDir;
    }

    @Deprecated
    public void setOutDir(File outDir) {
      this.outDir = outDir;
    }

    public void setWarDir(File warDir) {
      this.warDir = warDir;
    }
  }

  public static void legacyLink(TreeLogger logger, ModuleDef module,
      ArtifactSet generatedArtifacts, Permutation[] permutations,
      List<FileBackedObject<PermutationResult>> resultFiles, File outDir,
      JJSOptions precompileOptions) throws UnableToCompleteException,
      IOException {
    StandardLinkerContext linkerContext = new StandardLinkerContext(logger,
        module, precompileOptions);
    ArtifactSet artifacts = doSimulatedShardingLink(logger, module,
        linkerContext, generatedArtifacts, permutations, resultFiles);
    OutputFileSet outFileSet = chooseOutputFileSet(outDir, module.getName()
        + "/");
    OutputFileSet extraFileSet = chooseOutputFileSet(outDir, module.getName()
        + "-aux/");
    doProduceOutput(logger, artifacts, linkerContext, outFileSet, extraFileSet);
  }

  public static void link(TreeLogger logger, ModuleDef module,
      ArtifactSet generatedArtifacts, Permutation[] permutations,
      List<FileBackedObject<PermutationResult>> resultFiles, File outDir,
      File extrasDir, JJSOptions precompileOptions)
      throws UnableToCompleteException, IOException {
    StandardLinkerContext linkerContext = new StandardLinkerContext(logger,
        module, precompileOptions);
    ArtifactSet artifacts = doSimulatedShardingLink(logger, module,
        linkerContext, generatedArtifacts, permutations, resultFiles);
    doProduceOutput(logger, artifacts, linkerContext, chooseOutputFileSet(
        outDir, module.getName() + "/"), chooseOutputFileSet(extrasDir,
        module.getName() + "/"));
  }

  /**
   * This link operation is performed on a CompilePerms shard for one
   * permutation. It sees the generated artifacts for one permutation compile,
   * and it runs the per-permutation part of each shardable linker.
   */
  @SuppressWarnings("unchecked")
  public static void linkOnePermutationToJar(TreeLogger logger,
      ModuleDef module, ArtifactSet generatedArtifacts,
      PermutationResult permResult, File jarFile,
      PrecompileOptions precompileOptions) throws UnableToCompleteException {
    try {
      if (jarFile.exists()) {
        boolean success = jarFile.delete();
        if (!success) {
          logger.log(Type.ERROR, "Linker output file " + jarFile.getName() 
              + " already exists and can't be deleted.");
        }
      }
      JarOutputStream jar = new JarOutputStream(new FileOutputStream(jarFile));

      StandardLinkerContext linkerContext = new StandardLinkerContext(logger,
          module, precompileOptions);

      StandardCompilationResult compilation = new StandardCompilationResult(
          permResult);
      addSelectionPermutations(compilation, permResult.getPermutation(),
          linkerContext);
      ArtifactSet permArtifacts = new ArtifactSet(generatedArtifacts);
      permArtifacts.addAll(permResult.getArtifacts());
      permArtifacts.add(compilation);

      ArtifactSet linkedArtifacts = linkerContext.invokeLinkForOnePermutation(
          logger, compilation, permArtifacts);

      // Write the data of emitted artifacts
      for (EmittedArtifact art : linkedArtifacts.find(EmittedArtifact.class)) {
        String jarEntryPath;
        if (art.isPrivate()) {
          String pathWithLinkerName = linkerContext.getExtraPathForLinker(
              art.getLinker(), art.getPartialPath());
          if (pathWithLinkerName.startsWith("/")) {
            // This happens if the linker has no extra path
            pathWithLinkerName = pathWithLinkerName.substring(1);
          }
          jarEntryPath = "aux/" + pathWithLinkerName;
        } else {
          jarEntryPath = "target/" + art.getPartialPath();
        }
        ZipEntry ze = new ZipEntry(jarEntryPath);
        ze.setTime(art.getLastModified());
        jar.putNextEntry(ze);
        art.writeTo(logger, jar);
        jar.closeEntry();
      }

      // Serialize artifacts marked as Transferable
      int numSerializedArtifacts = 0;
      // The raw type Artifact is to work around a Java compiler bug:
      // http://bugs.sun.com/view_bug.do?bug_id=6548436
      for (Artifact art : linkedArtifacts) {
        if (art.isTransferableFromShards() && !(art instanceof EmittedArtifact)) {
          String jarEntryPath = "arts/" + numSerializedArtifacts++;
          jar.putNextEntry(new ZipEntry(jarEntryPath));
          Util.writeObjectToStream(jar, art);
          jar.closeEntry();
        }
      }

      jar.close();
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR, "Error linking", e);
      throw new UnableToCompleteException();
    }
  }

  public static void main(String[] args) {
    boolean success = false;
    Event linkEvent = SpeedTracerLogger.start(CompilerEventType.LINK);
    /*
     * NOTE: main always exits with a call to System.exit to terminate any
     * non-daemon threads that were started in Generators. Typically, this is to
     * shutdown AWT related threads, since the contract for their termination is
     * still implementation-dependent.
     */
    final LinkOptions options = new LinkOptionsImpl();

    if (new ArgProcessor(options).processArgs(args)) {
      CompileTask task = new CompileTask() {
        public boolean run(TreeLogger logger) throws UnableToCompleteException {
          return new Link(options).run(logger);
        }
      };
      if (CompileTaskRunner.runWithAppropriateLogger(options, task)) {
        success = true;
      }
    }
    linkEvent.end();
    System.exit(success ? 0 : 1);
  }

  /**
   * In a parallel build, artifact sets are thinned down in transit between
   * compilation and linking. All emitted artifacts are changed to binary
   * emitted artifacts, and all other artifacts are dropped except @Transferable
   * ones. This method simulates the thinning that happens in a parallel build.
   */
  @SuppressWarnings("unchecked")
  public static ArtifactSet simulateTransferThinning(ArtifactSet artifacts,
      StandardLinkerContext context) {
    ArtifactSet thinnedArtifacts = new ArtifactSet();
    // The raw type Artifact is to work around a compiler bug:
    // http://bugs.sun.com/view_bug.do?bug_id=6548436
    for (Artifact artifact : artifacts) {
      if (artifact instanceof EmittedArtifact) {
        EmittedArtifact emittedArtifact = (EmittedArtifact) artifact;
        String path = getFullArtifactPath(emittedArtifact, context);
        thinnedArtifacts.add(new BinaryOnlyArtifactWrapper(path,
            emittedArtifact));
      } else if (artifact.isTransferableFromShards()) {
        thinnedArtifacts.add(artifact);
      }
    }

    return thinnedArtifacts;
  }

  /**
   * Add to a compilation result all of the selection permutations from its
   * associated permutation.
   */
  private static void addSelectionPermutations(
      StandardCompilationResult compilation, Permutation perm,
      StandardLinkerContext linkerContext) {
    for (StaticPropertyOracle propOracle : perm.getPropertyOracles()) {
      compilation.addSelectionPermutation(computeSelectionPermutation(
          linkerContext, propOracle));
      compilation.addSoftPermutation(computeSoftPermutation(linkerContext,
          propOracle));
    }
  }

  /**
   * Choose an output file set for the given <code>dirOrJar</code> based on its
   * name, whether it's null, and whether it already exists as a directory.
   */
  private static OutputFileSet chooseOutputFileSet(File dirOrJar,
      String pathPrefix) throws IOException {
    if (dirOrJar == null) {
      return new NullOutputFileSet();
    }

    String name = dirOrJar.getName();
    if (!dirOrJar.isDirectory()
        && (name.endsWith(".war") || name.endsWith(".jar") || name.endsWith(".zip"))) {
      return new OutputFileSetOnJar(dirOrJar, pathPrefix);
    } else {
      Util.recursiveDelete(new File(dirOrJar, pathPrefix), true);
      return new OutputFileSetOnDirectory(dirOrJar, pathPrefix);
    }
  }

  /**
   * Return a map giving the value of each non-trivial selection property.
   */
  private static Map<SelectionProperty, String> computeSelectionPermutation(
      StandardLinkerContext linkerContext, StaticPropertyOracle propOracle) {
    BindingProperty[] orderedProps = propOracle.getOrderedProps();
    String[] orderedPropValues = propOracle.getOrderedPropValues();
    Map<SelectionProperty, String> unboundProperties = new HashMap<SelectionProperty, String>();
    for (int i = 0; i < orderedProps.length; i++) {
      SelectionProperty key = linkerContext.getProperty(orderedProps[i].getName());
      if (key.tryGetValue() != null) {
        /*
         * The view of the Permutation doesn't include properties with defined
         * values.
         */
        continue;
      } else if (key.isDerived()) {
        /*
         * The property provider does not need to be invoked, because the value
         * is determined entirely by other properties.
         */
        continue;
      }
      unboundProperties.put(key, orderedPropValues[i]);
    }
    return unboundProperties;
  }

  private static Map<SelectionProperty, String> computeSoftPermutation(
      StandardLinkerContext linkerContext, StaticPropertyOracle propOracle) {
    BindingProperty[] orderedProps = propOracle.getOrderedProps();
    String[] orderedPropValues = propOracle.getOrderedPropValues();
    Map<SelectionProperty, String> softProperties = new HashMap<SelectionProperty, String>();
    for (int i = 0; i < orderedProps.length; i++) {
      if (orderedProps[i].getCollapsedValues().isEmpty()) {
        continue;
      }

      SelectionProperty key = linkerContext.getProperty(orderedProps[i].getName());
      softProperties.put(key, orderedPropValues[i]);
    }
    return softProperties;
  }

  /**
   * Emit final output.
   */
  private static void doProduceOutput(TreeLogger logger, ArtifactSet artifacts,
      StandardLinkerContext linkerContext, OutputFileSet outFileSet,
      OutputFileSet extraFileSet) throws UnableToCompleteException, IOException {
    linkerContext.produceOutput(logger, artifacts, false, outFileSet);
    linkerContext.produceOutput(logger, artifacts, true, extraFileSet);

    outFileSet.close();
    extraFileSet.close();

    logger.log(TreeLogger.INFO, "Link succeeded");
  }

  /**
   * This link operation simulates sharded linking even though all generating
   * and linking is happening on the same computer. It can tolerate
   * non-shardable linkers.
   */
  private static ArtifactSet doSimulatedShardingLink(TreeLogger logger,
      ModuleDef module, StandardLinkerContext linkerContext,
      ArtifactSet generatedArtifacts, Permutation[] perms,
      List<FileBackedObject<PermutationResult>> resultFiles)
      throws UnableToCompleteException {
    ArtifactSet combinedArtifacts = new ArtifactSet();
    for (int i = 0; i < perms.length; ++i) {
      ArtifactSet newArtifacts = finishPermutation(logger, perms[i],
          resultFiles.get(i), linkerContext, generatedArtifacts);
      combinedArtifacts.addAll(newArtifacts);
    }

    combinedArtifacts.addAll(linkerContext.getArtifactsForPublicResources(
        logger, module));

    ArtifactSet legacyLinkedArtifacts = linkerContext.invokeLegacyLinkers(
        logger, combinedArtifacts);

    ArtifactSet thinnedArtifacts = simulateTransferThinning(
        legacyLinkedArtifacts, linkerContext);

    return linkerContext.invokeFinalLink(logger, thinnedArtifacts);
  }

  /**
   * Add a compilation to a linker context. Also runs the shardable part of all
   * linkers that support sharding.
   *
   * @return the new artifacts generated by the shardable part of this link
   *         operation
   */
  private static ArtifactSet finishPermutation(TreeLogger logger,
      Permutation perm, FileBackedObject<PermutationResult> resultFile,
      StandardLinkerContext linkerContext, ArtifactSet generatedArtifacts)
      throws UnableToCompleteException {
    PermutationResult permResult = resultFile.newInstance(logger);
    StandardCompilationResult compilation = new StandardCompilationResult(
        permResult);
    addSelectionPermutations(compilation, perm, linkerContext);
    logScriptSize(logger, perm.getId(), compilation);

    ArtifactSet permArtifacts = new ArtifactSet(generatedArtifacts);
    permArtifacts.addAll(permResult.getArtifacts());
    permArtifacts.add(compilation);
    permArtifacts.freeze();
    return linkerContext.invokeLinkForOnePermutation(logger, compilation,
        permArtifacts);
  }

  private static String getFullArtifactPath(EmittedArtifact emittedArtifact,
      StandardLinkerContext context) {
    String path = emittedArtifact.getPartialPath();
    if (emittedArtifact.isPrivate()) {
      path = context.getExtraPathForLinker(emittedArtifact.getLinker(), path);
      if (path.startsWith("/")) {
        // This happens if the linker has no extra path
        path = path.substring(1);
      }
    }
    return path;
  }

  /**
   * Logs the total script size for this permutation, as calculated by
   * {@link CodeSplitter#totalScriptSize(int[])}.
   */
  private static void logScriptSize(TreeLogger logger, int permId,
      StandardCompilationResult compilation) {
    if (!logger.isLoggable(TreeLogger.TRACE)) {
      return;
    }

    String[] javaScript = compilation.getJavaScript();

    int[] jsLengths = new int[javaScript.length];
    for (int i = 0; i < javaScript.length; i++) {
      jsLengths[i] = javaScript[i].length();
    }

    int totalSize = CodeSplitter.totalScriptSize(jsLengths);

    logger.log(TreeLogger.TRACE, "Permutation " + permId + " (strong name "
        + compilation.getStrongName() + ") has an initial download size of "
        + javaScript[0].length() + " and total script size of " + totalSize);
  }

  private static ArtifactSet scanCompilePermResults(TreeLogger logger,
      List<File> resultFiles) throws IOException, UnableToCompleteException {
    final ArtifactSet artifacts = new ArtifactSet();

    for (File resultFile : resultFiles) {
      JarFile jarFile = new JarFile(resultFile);
      Enumeration<JarEntry> entries = jarFile.entries();
      while (entries.hasMoreElements()) {
        JarEntry entry = entries.nextElement();
        if (entry.isDirectory()) {
          continue;
        }

        String path;
        Artifact<?> artForEntry;

        if (entry.getName().startsWith("target/")) {
          path = entry.getName().substring("target/".length());
          artForEntry = new JarEntryEmittedArtifact(path, resultFile, entry);
        } else if (entry.getName().startsWith("aux/")) {
          path = entry.getName().substring("aux/".length());
          JarEntryEmittedArtifact jarArtifact = new JarEntryEmittedArtifact(
              path, resultFile, entry);
          jarArtifact.setPrivate(true);
          artForEntry = jarArtifact;
        } else if (entry.getName().startsWith("arts/")) {
          try {
            artForEntry = Util.readStreamAsObject(new BufferedInputStream(
                jarFile.getInputStream(entry)), Artifact.class);
            assert artForEntry.isTransferableFromShards();
          } catch (ClassNotFoundException e) {
            logger.log(TreeLogger.ERROR,
                "Failed trying to deserialize an artifact", e);
            throw new UnableToCompleteException();
          }
        } else {
          continue;
        }

        artifacts.add(artForEntry);
      }

      jarFile.close();
    }

    return artifacts;
  }

  private final LinkOptionsImpl options;

  public Link(LinkOptions options) {
    this.options = new LinkOptionsImpl(options);
  }

  public boolean run(TreeLogger logger) throws UnableToCompleteException {
    loop_modules : for (String moduleName : options.getModuleNames()) {
      ModuleDef module = ModuleDefLoader.loadFromClassPath(logger, moduleName);

      File compilerWorkDir = options.getCompilerWorkDir(moduleName);
      PrecompilationResult precompileResults;
      try {
        precompileResults = Util.readFileAsObject(new File(compilerWorkDir,
            Precompile.PRECOMPILE_FILENAME), PrecompilationResult.class);
      } catch (ClassNotFoundException e) {
        logger.log(TreeLogger.ERROR, "Error reading "
            + Precompile.PRECOMPILE_FILENAME);
        return false;
      } catch (IOException e) {
        logger.log(TreeLogger.ERROR, "Error reading "
            + Precompile.PRECOMPILE_FILENAME);
        return false;
      }

      if (precompileResults instanceof PrecompileOptions) {
        /**
         * Precompiling happened on the shards.
         */
        if (!doLinkFinal(logger, compilerWorkDir, module,
            (JJSOptions) precompileResults)) {
          return false;
        }
        continue loop_modules;
      } else {
        /**
         * Precompiling happened on the start node.
         */
        Precompilation precomp = (Precompilation) precompileResults;
        Permutation[] perms = precomp.getPermutations();
        List<FileBackedObject<PermutationResult>> resultFiles = CompilePerms.makeResultFiles(
            compilerWorkDir, perms);

        // Check that all files are present
        for (FileBackedObject<PermutationResult> file : resultFiles) {
          if (!file.getFile().exists()) {
            logger.log(TreeLogger.ERROR, "File not found '"
                + file.getFile().getAbsolutePath()
                + "'; please compile all permutations");
            return false;
          }
        }

        TreeLogger branch = logger.branch(TreeLogger.INFO, "Linking module "
            + module.getName());

        try {
          link(branch, module, precomp.getGeneratedArtifacts(), perms,
              resultFiles, options.getWarDir(), options.getExtraDir(),
              precomp.getUnifiedAst().getOptions());
        } catch (IOException e) {
          logger.log(TreeLogger.ERROR,
              "Unexpected exception while producing output", e);
          throw new UnableToCompleteException();
        }
      }
    }
    return true;
  }

  /**
   * Do a final link, assuming the precompiles were done on the CompilePerms
   * shards.
   */
  private boolean doLinkFinal(TreeLogger logger, File compilerWorkDir,
      ModuleDef module, JJSOptions precompileOptions)
      throws UnableToCompleteException {
    int numPermutations = new PropertyPermutations(module.getProperties(),
        module.getActiveLinkerNames()).collapseProperties().size();
    List<File> resultFiles = new ArrayList<File>(numPermutations);
    for (int i = 0; i < numPermutations; ++i) {
      File f = CompilePerms.makePermFilename(compilerWorkDir, i);
      if (!f.exists()) {
        logger.log(TreeLogger.ERROR, "File not found '" + f.getAbsolutePath()
            + "'; please compile all permutations");
        return false;
      }
      resultFiles.add(f);
    }

    TreeLogger branch = logger.branch(TreeLogger.INFO, "Linking module "
        + module.getName());
    StandardLinkerContext linkerContext = new StandardLinkerContext(branch,
        module, precompileOptions);

    try {
      OutputFileSet outFileSet = chooseOutputFileSet(options.getWarDir(),
          module.getName() + "/");
      OutputFileSet extraFileSet = chooseOutputFileSet(options.getExtraDir(),
          module.getName() + "/");

      ArtifactSet artifacts = scanCompilePermResults(logger, resultFiles);
      artifacts.addAll(linkerContext.getArtifactsForPublicResources(logger,
          module));
      artifacts = linkerContext.invokeFinalLink(logger, artifacts);
      doProduceOutput(logger, artifacts, linkerContext, outFileSet,
          extraFileSet);
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR, "Exception during final linking", e);
      throw new UnableToCompleteException();
    }

    return true;
  }
}
