/*
 * 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.PropertyPermutations;
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 {
        compilerContext = compilerContextBuilder.options(options).build();
        ModuleDef module = ModuleDefLoader.loadFromClassPath(logger, compilerContext, moduleName);
        compilerContext = compilerContextBuilder.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.setOptimizePrecompile(false);
    precompilationOptions.setGenDir(null);
    compilerContext = compilerContextBuilder.options(precompilationOptions).build();

    ModuleDef module = ModuleDefLoader.loadFromClassPath(logger, compilerContext, moduleName);
    compilerContext = compilerContextBuilder.module(module).build();
    PropertyPermutations allPermutations = new PropertyPermutations(
        module.getProperties(), module.getActiveLinkerNames());
    List<PropertyPermutations> 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.
       */
      PropertyPermutations 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;
  }
}
