/*
 * 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.Linker;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.ModuleMetricsArtifact;
import com.google.gwt.core.ext.linker.PrecompilationMetricsArtifact;
import com.google.gwt.core.ext.linker.impl.StandardLinkerContext;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.dev.CompileTaskRunner.CompileTask;
import com.google.gwt.dev.cfg.ConfigurationProperty;
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.javac.CompilationState;
import com.google.gwt.dev.javac.CompilationUnit;
import com.google.gwt.dev.jjs.AbstractCompiler;
import com.google.gwt.dev.jjs.JavaScriptCompiler;
import com.google.gwt.dev.jjs.UnifiedAst;
import com.google.gwt.dev.shell.CheckForUpdates;
import com.google.gwt.dev.shell.CheckForUpdates.UpdateResult;
import com.google.gwt.dev.util.CollapsedPropertyKey;
import com.google.gwt.dev.util.Memory;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.collect.Lists;
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.File;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.concurrent.FutureTask;

/**
 * Performs the first phase of compilation, generating the set of permutations
 * to compile, and a ready-to-compile AST.
 */
public class Precompile {
  /**
   * The file name for the max number of permutations output as plain text.
   */
  static final String PERM_COUNT_FILENAME = "permCount.txt";

  static final String PRECOMPILE_FILENAME = Precompile.PRECOMPILE_FILENAME_PREFIX
      + Precompile.PRECOMPILE_FILENAME_SUFFIX;

  /**
   * The file name for the serialized AST artifact from the Precompile step.
   * Sometimes this file is overloaded and only contains a PrecompileOptions
   * object to indicate that precompilation should run inside the CompilePerms
   * step.
   */
  static final String PRECOMPILE_FILENAME_PREFIX = "precompilation";

  static final String PRECOMPILE_FILENAME_SUFFIX = ".ser";

  /**
   * Performs a command-line precompile.
   */
  public static void main(String[] args) {
    Memory.initialize();
    SpeedTracerLogger.init();
    Event precompileEvent = SpeedTracerLogger.start(CompilerEventType.PRECOMPILE);
    if (System.getProperty("gwt.jjs.dumpAst") != null) {
      System.out.println("Will dump AST to: " + System.getProperty("gwt.jjs.dumpAst"));
    }

    /*
     * 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 PrecompileTaskOptions options = new PrecompileTaskOptionsImpl();
    boolean success = false;
    if (new PrecompileTaskArgProcessor(options).processArgs(args)) {
      CompileTask task = new CompileTask() {
        @Override
        public boolean run(TreeLogger logger) throws UnableToCompleteException {
          FutureTask<UpdateResult> updater = null;
          if (!options.isUpdateCheckDisabled()) {
            updater =
                CheckForUpdates.checkForUpdatesInBackgroundThread(logger, CheckForUpdates.ONE_DAY);
          }
          boolean success = new Precompile(options).run(logger);
          if (success) {
            CheckForUpdates.logUpdateAvailable(logger, updater);
          }
          return success;
        }
      };
      if (CompileTaskRunner.runWithAppropriateLogger(options, task)) {
        // Exit w/ success code.
        success = true;
      }
    }
    precompileEvent.end();
    System.exit(success ? 0 : 1);
  }

  /**
   * Precompiles the given module.
   *
   * @param logger a logger to use
   * @param compilerContext shared read only compiler state
   * @return the precompilation
   * @throws UnableToCompleteException
   */
  public static Precompilation precompile(TreeLogger logger, CompilerContext compilerContext)
      throws UnableToCompleteException {
    PropertyPermutations allPermutations = new PropertyPermutations(
        compilerContext.getModule().getProperties(),
        compilerContext.getModule().getActiveLinkerNames());
    return precompile(logger, compilerContext, 0, allPermutations);
  }

  /**
   * Validates the given module can be compiled.
   *
   * @param logger a logger to use
   * @param compilerContext shared read only compiler state
   */
  public static boolean validate(TreeLogger logger, CompilerContext compilerContext) {
    Event validateEvent = SpeedTracerLogger.start(CompilerEventType.VALIDATE);
    try {
      ModuleDef module = compilerContext.getModule();
      PrecompileTaskOptions jjsOptions = compilerContext.getOptions();
      CompilationState compilationState = module.getCompilationState(logger, compilerContext);
      if (jjsOptions.isStrict() && compilationState.hasErrors()) {
        abortDueToStrictMode(logger);
      }
      String[] declEntryPts = module.getEntryPointTypeNames();
      String[] additionalRootTypes = null;
      if (declEntryPts.length == 0) {
        // No declared entry points, just validate all visible classes.
        Collection<CompilationUnit> compilationUnits = compilationState.getCompilationUnits();
        additionalRootTypes = new String[compilationUnits.size()];
        int i = 0;
        for (CompilationUnit unit : compilationUnits) {
          additionalRootTypes[i++] = unit.getTypeName();
        }
      }

      ArtifactSet generatorArtifacts = new ArtifactSet();
      DistillerRebindPermutationOracle rpo = new DistillerRebindPermutationOracle(
          compilerContext, compilationState, generatorArtifacts,
          new PropertyPermutations(module.getProperties(), module.getActiveLinkerNames()));
      // Allow GC later.
      compilationState = null;
      // Never optimize on a validation run.
      jjsOptions.setOptimizePrecompile(false);
      getCompiler(module).precompile(
          logger, compilerContext, rpo, declEntryPts, additionalRootTypes, true, null);
      return true;
    } catch (UnableToCompleteException e) {
      // Already logged.
      return false;
    } finally {
      validateEvent.end();
    }
  }

  /**
   * Create a list of all possible permutations configured for this module after
   * collapsing soft permutations.
   */
  static List<PropertyPermutations> getCollapsedPermutations(ModuleDef module) {
    PropertyPermutations allPermutations =
        new PropertyPermutations(module.getProperties(), module.getActiveLinkerNames());
    List<PropertyPermutations> collapsedPermutations = allPermutations.collapseProperties();
    return collapsedPermutations;
  }

  static AbstractCompiler getCompiler(ModuleDef module) {
    ConfigurationProperty compilerClassProp =
        module.getProperties().createConfiguration("x.compiler.class", false);
    String compilerClassName = compilerClassProp.getValue();
    if (compilerClassName == null || compilerClassName.length() == 0) {
      return new JavaScriptCompiler();
    }
    Throwable caught;
    try {
      Class<?> compilerClass = Class.forName(compilerClassName);
      return (AbstractCompiler) compilerClass.newInstance();
    } catch (ClassNotFoundException e) {
      caught = e;
    } catch (InstantiationException e) {
      caught = e;
    } catch (IllegalAccessException e) {
      caught = e;
    }
    throw new RuntimeException("Unable to instantiate compiler class '" + compilerClassName + "'",
        caught);
  }

  static Precompilation precompile(TreeLogger logger, CompilerContext compilerContext,
      int permutationBase, PropertyPermutations allPermutations) {
    return precompile(logger, compilerContext, permutationBase, allPermutations,
        ManagementFactory.getRuntimeMXBean().getStartTime());
  }

  static Precompilation precompile(TreeLogger logger, CompilerContext compilerContext,
      int permutationBase, PropertyPermutations allPermutations, long startTimeMilliseconds) {

    Event precompileEvent = SpeedTracerLogger.start(CompilerEventType.PRECOMPILE);

    // This initializes the Java2D library in a thread so that the main program
    // doesn't block when the library is accessed for the first time.
    new GraphicsInitThread().start();

    ArchivePreloader.preloadArchives(logger, compilerContext.getModule());

    try {
      ModuleDef module = compilerContext.getModule();
      PrecompileTaskOptions jjsOptions = compilerContext.getOptions();
      CompilationState compilationState = module.getCompilationState(logger, compilerContext);
      if (jjsOptions.isStrict() && compilationState.hasErrors()) {
        abortDueToStrictMode(logger);
      }

      List<String> initialTypeOracleTypes = new ArrayList<String>();
      if (jjsOptions.isCompilerMetricsEnabled()) {
        for (JClassType type : compilationState.getTypeOracle().getTypes()) {
          initialTypeOracleTypes.add(type.getPackage().getName() + "." + type.getName());
        }
      }

      // Track information about the module load including initial type
      // oracle build for diagnostic purposes.
      long moduleLoadFinished = System.currentTimeMillis();

      String[] declEntryPts = module.getEntryPointTypeNames();
      if (declEntryPts.length == 0) {
        logger.log(TreeLogger.ERROR, "Module has no entry points defined", null);
        throw new UnableToCompleteException();
      }

      ArtifactSet generatedArtifacts = new ArtifactSet();
      DistillerRebindPermutationOracle rpo = new DistillerRebindPermutationOracle(
          compilerContext, compilationState, generatedArtifacts, allPermutations);
      // Allow GC later.
      compilationState = null;
      PrecompilationMetricsArtifact precompilationMetrics =
          jjsOptions.isCompilerMetricsEnabled()
              ? new PrecompilationMetricsArtifact(permutationBase) : null;
      UnifiedAst unifiedAst =
          getCompiler(module).precompile(logger, compilerContext, rpo, declEntryPts, null,
              rpo.getPermutationCount() == 1, precompilationMetrics);

      if (jjsOptions.isCompilerMetricsEnabled()) {
        ModuleMetricsArtifact moduleMetrics = new ModuleMetricsArtifact();
        moduleMetrics.setSourceFiles(module.getAllSourceFiles());
        // The initial type list has to be gathered before the call to
        // precompile().
        moduleMetrics.setInitialTypes(initialTypeOracleTypes);
        // The elapsed time in ModuleMetricsArtifact represents time
        // which could be done once for all permutations.
        moduleMetrics.setElapsedMilliseconds(moduleLoadFinished - startTimeMilliseconds);
        unifiedAst.setModuleMetrics(moduleMetrics);
      }

      // Merge all identical permutations together.
      List<Permutation> permutations =
          new ArrayList<Permutation>(Arrays.asList(rpo.getPermutations()));

      mergeCollapsedPermutations(permutations);

      // Sort the permutations by an ordered key to ensure determinism.
      SortedMap<RebindAnswersPermutationKey, Permutation> merged =
          new TreeMap<RebindAnswersPermutationKey, Permutation>();
      SortedSet<String> liveRebindRequests = unifiedAst.getRebindRequests();
      for (Permutation permutation : permutations) {
        // Construct a key for the live rebind answers.
        RebindAnswersPermutationKey key =
            new RebindAnswersPermutationKey(permutation, liveRebindRequests);
        if (merged.containsKey(key)) {
          Permutation existing = merged.get(key);
          existing.mergeFrom(permutation, liveRebindRequests);
        } else {
          merged.put(key, permutation);
        }
      }
      if (jjsOptions.isCompilerMetricsEnabled()) {
        int[] ids = new int[allPermutations.size()];
        for (int i = 0; i < allPermutations.size(); i++) {
          ids[i] = permutationBase + i;
        }
        precompilationMetrics.setPermutationIds(ids);
        // TODO(zundel): Right now this double counts module load and
        // precompile time. It correctly counts the amount of time spent
        // in this process. The elapsed time in ModuleMetricsArtifact
        // represents time which could be done once for all permutations.
        precompilationMetrics.setElapsedMilliseconds(System.currentTimeMillis()
            - startTimeMilliseconds);
        unifiedAst.setPrecompilationMetrics(precompilationMetrics);
      }
      return new Precompilation(unifiedAst, merged.values(), permutationBase, generatedArtifacts);
    } catch (UnableToCompleteException e) {
      // We intentionally don't pass in the exception here since the real
      // cause has been logged.
      return null;
    } finally {
      precompileEvent.end();
    }
  }

  private static void abortDueToStrictMode(TreeLogger logger) throws UnableToCompleteException {
    logger.log(TreeLogger.ERROR, "Aborting compile due to errors in some input files");
    throw new UnableToCompleteException();
  }

  /**
   * This merges Permutations that can be considered equivalent by considering
   * their collapsed properties. The list passed into this method may have
   * elements removed from it.
   */
  private static void mergeCollapsedPermutations(List<Permutation> permutations) {
    if (permutations.size() < 2) {
      return;
    }

    // See the doc for CollapsedPropertyKey
    SortedMap<CollapsedPropertyKey, List<Permutation>> mergedByCollapsedProperties =
        new TreeMap<CollapsedPropertyKey, List<Permutation>>();

    // This loop creates the equivalence sets
    for (Iterator<Permutation> it = permutations.iterator(); it.hasNext();) {
      Permutation entry = it.next();
      CollapsedPropertyKey key = new CollapsedPropertyKey(entry);

      List<Permutation> equivalenceSet = mergedByCollapsedProperties.get(key);
      if (equivalenceSet == null) {
        equivalenceSet = Lists.create();
      } else {
        // Mutate list
        it.remove();
        equivalenceSet = Lists.add(equivalenceSet, entry);
      }
      mergedByCollapsedProperties.put(key, equivalenceSet);
    }

    // This loop merges the Permutations together
    for (Map.Entry<CollapsedPropertyKey, List<Permutation>> entry : mergedByCollapsedProperties
        .entrySet()) {
      Permutation mergeInto = entry.getKey().getPermutation();

      /*
       * Merge the deferred-binding properties once we no longer need the
       * PropertyOracle data from the extra permutations.
       */
      for (Permutation mergeFrom : entry.getValue()) {
        mergeInto.mergeRebindsFromCollapsed(mergeFrom);
      }
    }

    // Renumber the Permutations
    for (int i = 0, j = permutations.size(); i < j; i++) {
      permutations.set(i, new Permutation(i, permutations.get(i)));
    }
  }

  private final PrecompileTaskOptionsImpl options;

  private CompilerContext compilerContext;

  private final CompilerContext.Builder compilerContextBuilder = new CompilerContext.Builder();

  public Precompile(PrecompileTaskOptions options) {
    this.options = new PrecompileTaskOptionsImpl(options);
    compilerContext = compilerContextBuilder.options(options).build();
  }

  public boolean run(TreeLogger logger) throws UnableToCompleteException {
    // Avoid early optimizations since permutation compiles will run
    // separately.
    options.setOptimizePrecompile(false);

    for (String moduleName : options.getModuleNames()) {
      File compilerWorkDir = options.getCompilerWorkDir(moduleName);
      Util.recursiveDelete(compilerWorkDir, true);
      // No need to check mkdirs result because an IOException will occur
      // anyway.
      compilerWorkDir.mkdirs();

      File precompilationFile = new File(compilerWorkDir, PRECOMPILE_FILENAME);

      ModuleDef module =
          ModuleDefLoader.loadFromClassPath(logger, compilerContext, moduleName);
      compilerContext = compilerContextBuilder.module(module).build();

      StandardLinkerContext linkerContext =
          new StandardLinkerContext(TreeLogger.NULL, module, options);

      boolean generateOnShards = true;

      if (!options.isEnabledGeneratingOnShards()) {
        logger.log(TreeLogger.INFO, "Precompiling on the start node");
        generateOnShards = false;
      } else if (!linkerContext.allLinkersAreShardable()) {
        TreeLogger legacyLinkersLogger =
            logger.branch(TreeLogger.INFO,
                "Precompiling on the start node, because some linkers are not updated");
        if (legacyLinkersLogger.isLoggable(TreeLogger.INFO)) {
          for (Linker linker : linkerContext.findUnshardableLinkers()) {
            legacyLinkersLogger.log(TreeLogger.INFO, "Linker"
                + linker.getClass().getCanonicalName() + " is not updated");
          }
        }
        generateOnShards = false;
      } else if (options.isValidateOnly()) {
        // Don't bother running on shards for just a validation run
        generateOnShards = false;
      }

      if (generateOnShards) {
        /*
         * Pre-precompile. Count the permutations and plan to do a real
         * precompile in the CompilePerms shards.
         */
        TreeLogger branch =
            logger.branch(TreeLogger.INFO, "Precompiling (minimal) module " + module.getName());
        Util.writeObjectAsFile(logger, precompilationFile, options);
        int numPermutations =
            new PropertyPermutations(module.getProperties(), module.getActiveLinkerNames())
                .collapseProperties().size();
        Util.writeStringAsFile(logger, new File(compilerWorkDir, PERM_COUNT_FILENAME), String
            .valueOf(numPermutations));
        if (branch.isLoggable(TreeLogger.INFO)) {
          branch.log(TreeLogger.INFO,
              "Precompilation (minimal) succeeded, number of permutations: " + numPermutations);
        }
      } else {
        if (options.isValidateOnly()) {
          TreeLogger branch =
              logger.branch(TreeLogger.INFO, "Validating compilation " + module.getName());
          if (!validate(branch, compilerContext)) {
            branch.log(TreeLogger.ERROR, "Validation failed");
            return false;
          }
          branch.log(TreeLogger.INFO, "Validation succeeded");
        } else {
          TreeLogger branch =
              logger.branch(TreeLogger.INFO, "Precompiling module " + module.getName());

          Precompilation precompilation = precompile(branch, compilerContext);
          if (precompilation == null) {
            branch.log(TreeLogger.ERROR, "Precompilation failed");
            return false;
          }
          // TODO: move to precompile() after params are refactored
          if (!options.shouldSaveSource()) {
            precompilation.removeSourceArtifacts(logger);
          }
          Util.writeObjectAsFile(logger, precompilationFile, precompilation);

          int permsPrecompiled = precompilation.getPermutations().length;
          Util.writeStringAsFile(logger, new File(compilerWorkDir, PERM_COUNT_FILENAME), String
              .valueOf(permsPrecompiled));
          if (branch.isLoggable(TreeLogger.INFO)) {
            branch.log(TreeLogger.INFO, "Precompilation succeeded, number of permutations: "
                + permsPrecompiled);
          }
        }
      }
    }
    return true;
  }
}
