/*
 * 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.UnableToCompleteException;
import com.google.gwt.dev.CompileTaskRunner.CompileTask;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.ModuleDefLoader;
import com.google.gwt.dev.cfg.PropertyCombinations;
import com.google.gwt.dev.jjs.JavaToJavaScriptCompiler;
import com.google.gwt.dev.jjs.PermutationResult;
import com.google.gwt.dev.jjs.UnifiedAst;
import com.google.gwt.dev.util.FileBackedObject;
import com.google.gwt.dev.util.MemoryBackedObject;
import com.google.gwt.dev.util.PerfCounter;
import com.google.gwt.dev.util.PersistenceBackedObject;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.arg.ArgHandlerLocalWorkers;
import com.google.gwt.dev.util.arg.OptionLocalWorkers;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.util.tools.ArgHandlerString;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * Performs the second phase of compilation, converting the Precompile's AST
 * into JavaScript outputs.
 */
public class CompilePerms {

  /**
   * Options for CompilePerms.
   */
  public interface CompilePermsOptions extends PrecompileTaskOptions,
      OptionLocalWorkers, OptionPerms {
  }

  /**
   * Handles options for which permutations to compile.
   */
  public interface OptionPerms {
    /**
     * Gets the ordered set of permutations to compile. Returns a zero-length
     * array if all permutations should be compiled.
     */
    int[] getPermsToCompile();

    /**
     * Adds another permutation to compile.
     */
    void setPermsToCompile(int[] permsToCompile);
  }

  /**
   * Argument handler for specifying the which perms to run.
   */
  protected static final class ArgHandlerPerms extends ArgHandlerString {
    private final OptionPerms option;

    public ArgHandlerPerms(OptionPerms option) {
      this.option = option;
    }

    @Override
    public String getPurpose() {
      return "Comma-delimited list of 0-based permutations to compile";
    }

    @Override
    public String getTag() {
      return "-perms";
    }

    @Override
    public String[] getTagArgs() {
      return new String[]{"permlist"};
    }

    @Override
    public boolean setString(String str) {
      String[] split = str.split(",");
      if (split.length < 1) {
        System.err.println(getTag()
            + " requires a comma-delimited list of integers");
        return false;
      }

      SortedSet<Integer> permSet = new TreeSet<Integer>();
      for (String item : split) {
        try {
          int value = Integer.parseInt(item);
          if (value < 0) {
            System.err.println(getTag() + " error: negative value '" + value
                + "' is not allowed");
            return false;
          }
          permSet.add(value);
        } catch (NumberFormatException e) {
          System.err.println(getTag()
              + " requires a comma-delimited list of integers; '" + item
              + "' is not an integer");
          return false;
        }
      }
      int[] permsToCompile = new int[permSet.size()];
      int i = 0;
      for (int perm : permSet) {
        permsToCompile[i++] = perm;
      }
      option.setPermsToCompile(permsToCompile);
      return true;
    }
  }

  static class ArgProcessor extends PrecompileTaskArgProcessor {
    public ArgProcessor(CompilePermsOptions options) {
      super(options);
      registerHandler(new ArgHandlerPerms(options));
      registerHandler(new ArgHandlerLocalWorkers(options));
    }

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

  /**
   * Concrete class to implement compiler perm options.
   */
  static class CompilePermsOptionsImpl extends PrecompileTaskOptionsImpl implements
      CompilePermsOptions {

    private int localWorkers;
    private int[] permsToCompile;

    public CompilePermsOptionsImpl() {
    }

    public CompilePermsOptionsImpl(CompilePermsOptions other) {
      copyFrom(other);
    }

    public void copyFrom(CompilePermsOptions other) {
      super.copyFrom(other);
      setPermsToCompile(other.getPermsToCompile());
      setLocalWorkers(other.getLocalWorkers());
    }

    @Override
    public int getLocalWorkers() {
      return localWorkers;
    }

    @Override
    public int[] getPermsToCompile() {
      return (permsToCompile == null) ? null : permsToCompile.clone();
    }

    @Override
    public void setLocalWorkers(int localWorkers) {
      this.localWorkers = localWorkers;
    }

    @Override
    public void setPermsToCompile(int[] permsToCompile) {
      this.permsToCompile = (permsToCompile == null) ? null
          : permsToCompile.clone();
    }
  }

  /**
   * Compile a single permutation.
   *
   * @throws UnableToCompleteException if the permutation compile fails
   */
  public static PermutationResult compile(TreeLogger logger, CompilerContext compilerContext,
      Permutation permutation, UnifiedAst unifiedAst) throws UnableToCompleteException {
    return JavaToJavaScriptCompiler.compilePermutation(unifiedAst, logger, compilerContext,
        permutation);
  }

  /**
   * Compile multiple permutations.
   */
  public static void compile(TreeLogger logger, CompilerContext compilerContext,
      Precompilation precompilation, Permutation[] perms, int localWorkers,
      List<PersistenceBackedObject<PermutationResult>> resultFiles)
      throws UnableToCompleteException {
    final TreeLogger branch = logger.branch(TreeLogger.INFO,
        "Compiling " + perms.length + " permutation" + (perms.length > 1 ? "s" : ""));
    PermutationWorkerFactory.compilePermutations(
        branch, compilerContext, precompilation, perms, localWorkers, resultFiles);
    logger.log(TreeLogger.INFO, "Compile of permutations succeeded");
  }

  public static void main(String[] args) {
    int exitCode = -1;
    /*
     * 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 CompilePermsOptions options = new CompilePermsOptionsImpl();
    if (new ArgProcessor(options).processArgs(args)) {
      CompileTask task = new CompileTask() {
        @Override
        public boolean run(TreeLogger logger) throws UnableToCompleteException {
          return new CompilePerms(options).run(logger);
        }
      };
      if (CompileTaskRunner.runWithAppropriateLogger(options, task)) {
        // Exit w/ success code.
        exitCode = 0;
      }
    }
    PerfCounter.print();
    System.exit(exitCode);
  }

  public static List<PersistenceBackedObject<PermutationResult>> makeResultFiles(
      File compilerWorkDir, Permutation[] perms, PrecompileTaskOptions options) {
    List<PersistenceBackedObject<PermutationResult>> toReturn = Lists.newArrayList();
    for (int i = 0; i < perms.length; ++i) {
      if (options.isIncrementalCompileEnabled()) {
        toReturn.add(new MemoryBackedObject<PermutationResult>(PermutationResult.class));
      } else {
        File f = makePermFilename(compilerWorkDir, perms[i].getId());
        toReturn.add(new FileBackedObject<PermutationResult>(PermutationResult.class, f));
      }
    }
    return toReturn;
  }

  /**
   * Return the filename corresponding to the given permutation number,
   * one-based.
   */
  static File makePermFilename(File compilerWorkDir, int permNumber) {
    return new File(compilerWorkDir, "permutation-" + permNumber + ".js");
  }

  static PrecompilationResult readPrecompilationFile(TreeLogger logger,
      File precompilationFile) {
    PrecompilationResult precompileResults = null;
    try {
      precompileResults = Util.readFileAsObject(precompilationFile,
          PrecompilationResult.class);
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR, "Failed to read "
          + precompilationFile + "\nHas Precompile been run?");
    } catch (ClassNotFoundException e) {
      logger.log(TreeLogger.ERROR, "Failed to read "
          + precompilationFile, e);
    }
    return precompileResults;
  }

  /**
   * Choose the subset of requested permutations that correspond to the
   * indicated precompilation.
   */
  static Permutation[] selectPermutationsForPrecompilation(
      int[] permsToRun, Precompilation precompilation) {
    if (permsToRun == null) {
      // Special case: compile everything.
      return precompilation.getPermutations();
    }
    ArrayList<Permutation> subPermsList = new ArrayList<Permutation>();
    for (int id : permsToRun) {
      for (Permutation perm : precompilation.getPermutations()) {
        if (perm.getId() == id) {
          subPermsList.add(perm);
        }
      }
    }
    return subPermsList.toArray(new Permutation[subPermsList.size()]);
  }

  private CompilerContext compilerContext;
  private CompilerContext.Builder compilerContextBuilder;
  private final CompilePermsOptionsImpl options;

  public CompilePerms(CompilePermsOptions options) {
    this.options = new CompilePermsOptionsImpl(options);
    compilerContextBuilder = new CompilerContext.Builder();
  }

  public boolean run(TreeLogger logger) throws UnableToCompleteException {
    for (String moduleName : options.getModuleNames()) {
      /*
       * NOTE: as a special case, null means "compile everything".
       */
      int[] permsToRun = options.getPermsToCompile();

      File compilerWorkDir = options.getCompilerWorkDir(moduleName);
      File precompilationFile = new File(compilerWorkDir,
          Precompile.PRECOMPILE_FILENAME);

      PrecompilationResult precompileResults = readPrecompilationFile(logger,
          precompilationFile);

      if (precompileResults instanceof PrecompileTaskOptions) {
        PrecompileTaskOptions precompilationOptions = (PrecompileTaskOptions) precompileResults;
        if (!precompileAndCompile(logger, moduleName, compilerWorkDir,
            precompilationOptions)) {
          return false;
        }
      } else {
        ModuleDef module = ModuleDefLoader.loadFromClassPath(logger, moduleName);
        compilerContext = compilerContextBuilder.options(options).module(module).build();
        Precompilation precompilation = (Precompilation) precompileResults;
        // Choose which permutations go with this permutation
        Permutation[] subPerms = selectPermutationsForPrecompilation(
            permsToRun, precompilation);

        List<PersistenceBackedObject<PermutationResult>> resultFiles = makeResultFiles(
            compilerWorkDir, subPerms, options);
        compile(logger, compilerContext, precompilation, subPerms,
            options.getLocalWorkers(), resultFiles);
      }
    }

    return true;
  }

  /**
   * Run both a precompile and a compile with the given precompilation options.
   */
  private boolean precompileAndCompile(TreeLogger logger, String moduleName,
      File compilerWorkDir, PrecompileTaskOptions precompilationOptions)
      throws UnableToCompleteException {
    precompilationOptions.setGenDir(null);

    ModuleDef module = ModuleDefLoader.loadFromClassPath(logger, moduleName);
    compilerContext = compilerContextBuilder.options(precompilationOptions).module(module).build();
    PropertyCombinations allPermutations = new PropertyCombinations(
        module.getProperties(), module.getActiveLinkerNames());
    List<PropertyCombinations> collapsedPermutations = allPermutations.collapseProperties();
    int[] perms = options.getPermsToCompile();
    if (perms == null) {
      perms = new int[collapsedPermutations.size()];
      for (int i = 0; i < perms.length; ++i) {
        perms[i] = i;
      }
    }

    logger = logger.branch(TreeLogger.INFO, "Compiling " + perms.length
        + " permutation" + (perms.length > 1 ? "s" : ""));
    for (int permId : perms) {
      /*
       * TODO(spoon,scottb): move Precompile out of the loop to run only once
       * per shard. Then figure out a way to avoid copying the generated
       * artifacts into every perm result on a shard.
       */
      PropertyCombinations onePerm = collapsedPermutations.get(permId);

      Precompilation precompilation =
          Precompile.precompile(logger, compilerContext, permId, onePerm);
      if (precompilation == null) {
        return false;
      }
      // TODO: move to precompile() after params are refactored
      if (!options.shouldSaveSource()) {
        precompilation.removeSourceArtifacts(logger);
      }

      // Choose which permutations go with this precompilation
      Permutation[] subPerms = selectPermutationsForPrecompilation(
          new int[]{permId}, precompilation);
      assert subPerms.length == 1;

      PermutationResult permResult =
          compile(logger, compilerContext, subPerms[0], precompilation.getUnifiedAst());
      Link.linkOnePermutationToJar(logger, compilerContext.getModule(),
          compilerContext.getPublicResourceOracle(), precompilation.getGeneratedArtifacts(),
          permResult, makePermFilename(compilerWorkDir, permId), compilerContext.getOptions());
    }

    logger.log(TreeLogger.INFO, "Compile of permutations succeeded");
    return true;
  }
}
