/*
 * Copyright 2010 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.jjs.PermutationResult;
import com.google.gwt.dev.util.PerfCounter;
import com.google.gwt.dev.util.arg.ArgHandlerPerm;
import com.google.gwt.dev.util.arg.OptionPerm;

import java.io.File;
import java.util.List;

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

  /**
   * Options for CompilePerm.
   */
  public interface CompileOnePermOptions extends PrecompileTaskOptions, OptionPerm {
  }

  static class ArgProcessor extends PrecompileTaskArgProcessor {
    public ArgProcessor(CompileOnePermOptions options) {
      super(options);
      registerHandler(new ArgHandlerPerm(options));
    }

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

  /**
   * Concrete class to implement compiler perm options.
   */
  static class CompileOnePermOptionsImpl extends PrecompileTaskOptionsImpl
      implements CompileOnePermOptions {

    private int permToCompile = -1;

    public CompileOnePermOptionsImpl() {
    }

    public CompileOnePermOptionsImpl(CompileOnePermOptions other) {
      copyFrom(other);
    }

    public void copyFrom(CompileOnePermOptions other) {
      super.copyFrom(other);
      setPermToCompile(other.getPermToCompile());
    }

    @Override
    public int getPermToCompile() {
      return permToCompile;
    }

    @Override
    public void setPermToCompile(int permToCompile) {
      this.permToCompile = permToCompile;
    }
  }

  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 CompileOnePermOptions options = new CompileOnePermOptionsImpl();
    if (new ArgProcessor(options).processArgs(args)) {
      CompileTask task = new CompileTask() {
        @Override
        public boolean run(TreeLogger logger) throws UnableToCompleteException {
          return new CompileOnePerm(options).run(logger);
        }
      };
      if (CompileTaskRunner.runWithAppropriateLogger(options, task)) {
        // Exit w/ success code.
        exitCode = 0;
      }
    }
    PerfCounter.print();
    System.exit(exitCode);
  }

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

  /**
   * Run Compile where precompilation occurred previously on sharded steps of
   * Precompile. There will be a different serialized AST file named
   * permutation-*.ser, one per permutation.
   *
   * @param logger tree logger
   * @param moduleName Name of the GWT module with the entry point
   * @param permId permutations to compile
   * @param compilerWorkDir directory where work files are stored
   *
   * @return <code>true</code> if compilation succeeds
   */
  private static boolean compileSpecificPermutation(TreeLogger logger,
      String moduleName, PrecompileTaskOptions precompilationOptions, int permId,
      File compilerWorkDir) throws UnableToCompleteException {
    CompilerContext.Builder compilerContextBuilder = new CompilerContext.Builder();
    CompilerContext compilerContext = compilerContextBuilder.options(precompilationOptions).build();
    ModuleDef module = ModuleDefLoader.loadFromClassPath(logger, compilerContext, moduleName);
    compilerContext = compilerContextBuilder.module(module).build();

    logger = logger.branch(TreeLogger.INFO, "Compiling permutation " + permId);

    File precompilationFile = new File(compilerWorkDir,
        PrecompileOnePerm.getPrecompileFilename(permId));
    Precompilation precompilation = (Precompilation) CompilePerms.readPrecompilationFile(
        logger, precompilationFile);

    // Choose the permutation that goes with this precompilation
    Permutation[] subPerms = CompilePerms.selectPermutationsForPrecompilation(
        new int[]{permId}, precompilation);
    assert subPerms.length == 1;

    PermutationResult permResult =
        precompilation.getUnifiedAst().compilePermutation(logger, compilerContext, subPerms[0]);
    Link.linkOnePermutationToJar(logger, module,
        precompilation.getGeneratedArtifacts(), permResult, makePermFilename(
            compilerWorkDir, permId), precompilationOptions);
    return true;
  }

  private final CompileOnePermOptionsImpl options;

  public CompileOnePerm(CompileOnePermOptions options) {
    this.options = new CompileOnePermOptionsImpl(options);
  }

  public boolean run(TreeLogger logger) throws UnableToCompleteException {
    List<String> moduleNames = options.getModuleNames();
    if (moduleNames.size() != 1) {
      logger.log(TreeLogger.ERROR, "Expected a single module name.");
      return false;
    }
    int permToRun = options.getPermToCompile();
    if (permToRun < 0) {
      logger.log(TreeLogger.ERROR,
          "Expected argument -perm to specify the permutation to compile.");
      return false;
    }

    String moduleName = moduleNames.get(0);
    File compilerWorkDir = options.getCompilerWorkDir(moduleName);

    // Look for the sentinel file that indicates that this compilation already
    // has a precompilation result from a previous Precompile step.
    PrecompileTaskOptions precompilationOptions = AnalyzeModule.readAnalyzeModuleOptionsFile(
        logger, compilerWorkDir);
    if (precompilationOptions == null) {
      logger.log(TreeLogger.ERROR, "Could not read file "
          + AnalyzeModule.OPTIONS_FILENAME + " output from AnalyzeModule step.");
      return false;
    }

    return compileSpecificPermutation(logger, moduleName,
        precompilationOptions, permToRun, compilerWorkDir);
  }
}
