/*
 * 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.jjs.impl.codesplitter;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JRunAsync;
import com.google.gwt.dev.jjs.impl.ControlFlowAnalyzer;
import com.google.gwt.dev.jjs.impl.JavaToJavaScriptMap;
import com.google.gwt.dev.js.ast.JsBlock;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsModVisitor;
import com.google.gwt.dev.js.ast.JsNumericEntry;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsStatement;
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 com.google.gwt.thirdparty.guava.common.base.Predicate;
import com.google.gwt.thirdparty.guava.common.collect.Collections2;
import com.google.gwt.thirdparty.guava.common.collect.Iterables;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Multimap;


import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * <p>
 * Divides the code in a {@link JsProgram} into multiple fragments. The initial
 * fragment is sufficient to run all of the program's functionality except for
 * anything called in a callback supplied to
 * {@link com.google.gwt.core.client.GWT#runAsync(com.google.gwt.core.client.RunAsyncCallback)
 * GWT.runAsync()}. The remaining code should be downloadable via
 * {@link com.google.gwt.core.client.impl.AsyncFragmentLoader#inject(int)}.
 * </p>
 *
 * <p>Code splitting is implemented in a two stage process: the first stage decides how runAsyncs
 * are grouped together and the second decides the code in each fragment by computing the
 * appropriate control flow analyses.
 * </p>
 *
 * <p> The first stage is implemented by a {@link FragmentPartitionStrategy}, that can use fast but
 * unsound analyses to determine how to group the runAsyncs together, its only requirement is that
 * the result is a partition of a subset of the runAsyncs. Currently two strategies are implemented:
 * (1) {@link OneToOneFragmentPartitionStrategy} that assigns each runAsync to one fragment (as in
 * the original CodeSplitter), and (2) {@link MergeBySimilarityFragmentPartitionStrategy}</p> where
 * runAsyncs are pairwise merged together into a predetermined maximum number of fragments is a
 * way that is estimated to minimize the leftover fragment size (which is the strategy previously
 * attempted in the now obsolete CodeSplitter2. Additionally if the option
 * {@link CodeSplitters.MIN_FRAGMENT_SIZE} is set, this strategy also merge fragments that are
 * smaller than the minimum fragments size together and if the resulting combined fragment is still
 * smaller than the minimum fragment size it is left out of the fragmentation so that it is merged
 * into the leftovers by the second stage.
 * <p>
 *
 * <p>
 * The second stage assigns program atoms that to fragments that exclusively use them, setting up
 * and extra fragment for the non exclusive atoms and the runAsyncs that were not assigned to any
 * fragment. Code that is activated when the application starts and runAsyncs that are part of the
 * {@link CodeSplitters.PROP_INITIAL_SEQUENCE} are excluded from the first stage and are treated as
 * special initial fragments that will be downloaded when the application starts.
 * Whenever this second stage is changed  <code>AsyncFragmentLoader</code> must be updated
 * in tandem.
 * </p>
 *
 * <p>
 * The fragment for a runAsync point contains different things depending on whether
 * it is in the initial load sequence or not. If it's in the initial load
 * sequence, then the fragment includes the code newly live once that split
 * point is crossed, that wasn't already live for the set of split points
 * earlier in the sequence. For a split point not in the initial load sequence,
 * the fragment contains only code exclusive to that split point, that is, code
 * that cannot be reached except via that split point. All other code goes into
 * the leftovers fragment.
 * </p>
 */
public class CodeSplitter {

  public static ControlFlowAnalyzer computeInitiallyLive(JProgram jprogram) {
    return computeInitiallyLive(jprogram, MultipleDependencyGraphRecorder.NULL_RECORDER);
  }

  public static void exec(TreeLogger logger, JProgram jprogram, JsProgram jsprogram,
      JavaToJavaScriptMap map, int expectedFragmentCount, int minFragmentSize,
      MultipleDependencyGraphRecorder dependencyRecorder) {
    if (jprogram.getRunAsyncs().isEmpty()) {
      // Don't do anything if there is no call to runAsync
      return;
    }
    Event codeSplitterEvent = SpeedTracerLogger.start(CompilerEventType.CODE_SPLITTER);
    dependencyRecorder.open();
    new CodeSplitter(logger, jprogram, jsprogram, map, expectedFragmentCount, minFragmentSize,
        dependencyRecorder).execImpl();
    dependencyRecorder.close();
    codeSplitterEvent.end();
  }

  /**
   * <p>
   * Computes the "maximum total script size" for one permutation. The total
   * script size for one sequence of split points reached is the sum of the
   * scripts that are downloaded for that sequence. The maximum total script
   * size is the maximum such size for all possible sequences of split points.
   * </p>
   *
   * @param jsLengths The lengths of the fragments for the compilation of one
   *          permutation
   */

  public static int computeTotalSize(int[] jsLengths) {
    /*
     * The total script size is currently simple: it's the sum of all the
     * individual script files.
     *
     * TODO(rluble): This function seems unnecessary and out of place here.
     */

    int totalSize = 0;
    for (int size : jsLengths) {
      totalSize += size;
    }
    return totalSize;
  }

  /**
   * Compute the set of initially live code for this program. Such code must be
   * included in the initial download of the program.
   */
  private static ControlFlowAnalyzer computeInitiallyLive(JProgram jprogram,
      MultipleDependencyGraphRecorder dependencyRecorder) {
    dependencyRecorder.startDependencyGraph("initial", null);

    ControlFlowAnalyzer cfa = new ControlFlowAnalyzer(jprogram);
    cfa.setDependencyRecorder(dependencyRecorder);
    cfa.traverseEntryMethods();
    computeLivenessFromCodeGenTypes(jprogram, cfa);
    dependencyRecorder.endDependencyGraph();
    return cfa;
  }

  /**
   * Any immortal codegen types must be part of the initial download.
   */
  private static void computeLivenessFromCodeGenTypes(JProgram jprogram,
      ControlFlowAnalyzer cfa) {
    for (JClassType type : jprogram.immortalCodeGenTypes) {
      cfa.traverseFromInstantiationOf(type);
      for (JMethod method : type.getMethods()) {
        if (!method.needsDynamicDispatch()) {
          cfa.traverseFrom(method);
        }
      }
    }
  }

  /**
   * Group run asyncs that have the same class literal as the first parameter in the two parameter
   * GWT.runAsync call.
   */
  private static Collection<Collection<JRunAsync>> groupAsyncsByClassLiteral(
      Collection<JRunAsync> runAsyncs) {
    Collection<Collection<JRunAsync>> result = Lists.newArrayList();
    Multimap<String, JRunAsync> asyncsGroupedByName =
        CodeSplitters.computeRunAsyncsByName(runAsyncs, true);
    // Add runAsyncs that have class literals in groups.
    result.addAll(asyncsGroupedByName.asMap().values());
    // Add all the rest.
    result.addAll(CodeSplitters.getListOfLists(Collections2.filter(runAsyncs,
        new Predicate<JRunAsync>() {
          @Override
          public boolean apply(JRunAsync runAsync) {
            return !runAsync.hasExplicitClassLiteral();
          }
        })));
    return result;
  }

  private final MultipleDependencyGraphRecorder dependencyRecorder;
  private final FragmentExtractor fragmentExtractor;
  private final LinkedHashSet<JRunAsync> initialLoadSequence;

  /**
   * Code that is initially live when the program first downloads.
   */
  private final ControlFlowAnalyzer initiallyLiveCfa;
  private final JProgram jprogram;
  private final JsProgram jsprogram;

  /**
   * Computed during {@link #execImpl()}, so that intermediate steps of it can
   * be used as they are created.
   */
  private ControlFlowAnalyzer initialSequenceCfa;
  private final TreeLogger logger;
  private final boolean logFragmentMap;
  private final JavaToJavaScriptMap map;
  private final Set<JMethod> methodsStillInJavaScript;

  private final List<Fragment> fragments = Lists.newArrayList();

  private final FragmentPartitionStrategy partitionStrategy;

  private CodeSplitter(TreeLogger logger, JProgram jprogram, JsProgram jsprogram,
      JavaToJavaScriptMap map, int expectedFragmentCount, int minFragmentSize,
      MultipleDependencyGraphRecorder dependencyRecorder) {
    this.logger = logger.branch(TreeLogger.TRACE, "Splitting JavaScript for incremental download");
    this.jprogram = jprogram;
    this.jsprogram = jsprogram;
    this.map = map;
    this.dependencyRecorder = dependencyRecorder;
    this.initialLoadSequence = jprogram.getInitialAsyncSequence();
    assert initialLoadSequence != null;

    logFragmentMap = Boolean.getBoolean(CodeSplitters.PROP_LOG_FRAGMENT_MAP);
    fragmentExtractor = new FragmentExtractor(jprogram, jsprogram, map);

    initiallyLiveCfa = computeInitiallyLive(jprogram, dependencyRecorder);

    methodsStillInJavaScript = fragmentExtractor.findAllMethodsStillInJavaScript();

    // TODO(rluble): expected fragment count is not enforced. the actual number
    // of fragments may be more or less....
    partitionStrategy = expectedFragmentCount > 0 ?
        new MergeBySimilarityFragmentPartitionStrategy(
            CodeSplitters.getNumberOfExclusiveFragmentFromExpectedFragmentCount(
                initialLoadSequence.size(), expectedFragmentCount), minFragmentSize) :
        new OneToOneFragmentPartitionStrategy();
  }

  /**
   * Compute the statements that go into a fragment.
   *
   * @param fragmentId the fragment number
   * @param alreadyLoaded The code that should be assumed to have already been
   *          loaded
   * @param liveNow The code that is assumed live once this fragment loads;
   *          anything in here but not in <code>alreadyLoaded</code> will be
   *          included in the created fragment
   */
  private List<JsStatement>  statementsForFragment(int fragmentId,
      LivenessPredicate alreadyLoaded, LivenessPredicate liveNow) {
    if (logFragmentMap) {
      System.out.println();
      System.out.println("==== Fragment " + fragmentId + " ====");
      fragmentExtractor.setStatementLogger(new EchoStatementLogger(map));
    }
    return fragmentExtractor.extractStatements(liveNow, alreadyLoaded);
  }

  /**
   * For each exclusive fragment (those that are not part of the initial load sequence) compute
   * a CFA that traces every split point not in the fragment; i.e. computes the atoms that are
   * live in (WholeProgram - Fragment).
   */
  private Map<Fragment, ControlFlowAnalyzer> computeNotExclusiveCfaForFragments(
      Collection<Fragment> exclusiveFragments) {
    String dependencyGraphNameAfterInitialSequence = dependencyGraphNameAfterInitialSequence();

    Map<Fragment, ControlFlowAnalyzer> notExclusiveCfaByFragment = Maps.newHashMap();

    for (Fragment fragment : exclusiveFragments) {
      assert fragment.isExclusive();

      dependencyRecorder.startDependencyGraph("sp" + fragment.getFragmentId(),
          dependencyGraphNameAfterInitialSequence);
      ControlFlowAnalyzer cfa = new ControlFlowAnalyzer(initialSequenceCfa);
      cfa.setDependencyRecorder(dependencyRecorder);
      for (Fragment otherFragment : exclusiveFragments) {
        // don't trace the initial fragments as they have already been traced and their atoms are
        // already in {@code initialSequenceCfa}.
        if (otherFragment.isInitial()) {
          continue;
        }
        if (otherFragment == fragment) {
          continue;
        }
        for (JRunAsync otherRunAsync : otherFragment.getRunAsyncs()) {
          cfa.traverseFromRunAsync(otherRunAsync);
        }
      }
      dependencyRecorder.endDependencyGraph();
      notExclusiveCfaByFragment.put(fragment, cfa);
    }
    return notExclusiveCfaByFragment;
  }

  /**
   * Compute a CFA that covers the entire live code of the program.
   */
  private ControlFlowAnalyzer computeCompleteCfa() {
    dependencyRecorder.startDependencyGraph("total", null);
    ControlFlowAnalyzer completeCfa = new ControlFlowAnalyzer(jprogram);
    completeCfa.setDependencyRecorder(dependencyRecorder);
    completeCfa.traverseEverything();
    dependencyRecorder.endDependencyGraph();
    return completeCfa;
  }

  /**
   * The name of the dependency graph that corresponds to
   * {@link #initialSequenceCfa}.
   */
  private String dependencyGraphNameAfterInitialSequence() {
    if (initialLoadSequence.isEmpty()) {
      return "initial";
    } else {
      return "sp" + Iterables.getLast(initialLoadSequence).getRunAsyncId();
    }
  }

  /**
   * Map each program atom as exclusive to some split point, whenever possible.
   * Also fixes up load order problems that could result from splitting code
   * based on this assumption.
   */
  private ExclusivityMap computeExclusivityMapWithFixups(Collection<Fragment> exclusiveFragments) {
    ControlFlowAnalyzer completeCfa = computeCompleteCfa();
    Map<Fragment, ControlFlowAnalyzer> notExclusiveCfaByFragment =
        computeNotExclusiveCfaForFragments(exclusiveFragments);
    ExclusivityMap exclusivityMap =  ExclusivityMap.computeExclusivityMap(exclusiveFragments,
        completeCfa, notExclusiveCfaByFragment);
    exclusivityMap.fixUpLoadOrderDependencies(logger, jprogram, methodsStillInJavaScript);
    return exclusivityMap;
  }

  /**
   * The current implementation of code splitting divides the program into fragments. There are
   * four different types of fragment.
   *   - initial download: the part of the program that will execute from the entry point and is
   *     not part of any runAsync. This fragment is implicit and there is not representation of
   *     it in the code splitter.
   *   - initial fragments: some runAsyncs are forced to be in the initial download by listing them
   *     in the {@link CodeSplitters.PROP_INITIAL_SEQUENCE} property. A separate fragment (Type.INITIAL)
   *     is created for each of there splitpoints and each contains only one splitpoit.
   *   - exclusive fragments: the remaining runAsyncs are assigned to some exclusive fragment. Many
   *     splitpoints may be in the same fragment but each of these splitpoints is in one and only
   *     one fragment. The fragmentation strategy assigns splitpoints to fragments.
   *   - leftover fragments: this is an artificial fragment that will contain all the atoms that
   *     are not in the initial and are not exclusive to a fragment.
   *
   *<p>Code splitting is a three stage process:
   *   - first the initial fragment are determined.
   *   - then a fragmentation strategy is run to partition runAsyncs into exclusive fragments.
   *   - lastly atoms that are not exclusive are assigned to the LEFT_OVERS fragment.
   */
  private void execImpl() {

    Fragment lastInitialFragment = null;

    // Fragments are numbered from 0.
    int nextFragmentIdToAssign = 0;

    // Step #1: Decide how to map splitpoints to fragments.
    {
      /*
       * Compute the base fragment. It includes everything that is live when the
       * program starts.
       */
      LivenessPredicate alreadyLoaded = new NothingAlivePredicate();
      LivenessPredicate liveNow = new CfaLivenessPredicate(initiallyLiveCfa);
      Fragment fragment =
          new Fragment(Fragment.Type.INITIAL);
      fragment.setFragmentId(nextFragmentIdToAssign++);
      List<JsStatement> statementsForFragment = statementsForFragment(fragment.getFragmentId(),
          alreadyLoaded, liveNow);
      fragment.setStatements(statementsForFragment);
      lastInitialFragment = fragment;
      fragments.add(fragment);
    }

    /*
     * Compute the base fragments, for split points in the initial load
     * sequence.
     */
    initialSequenceCfa = new ControlFlowAnalyzer(initiallyLiveCfa);
    String extendsCfa = "initial";
    List<Integer> initialFragmentNumberSequence = new ArrayList<Integer>();
    for (JRunAsync runAsync : initialLoadSequence) {
      LivenessPredicate alreadyLoaded = new CfaLivenessPredicate(initialSequenceCfa);

      String depGraphName = "sp" + runAsync.getRunAsyncId();
      dependencyRecorder.startDependencyGraph(depGraphName, extendsCfa);
      extendsCfa = depGraphName;

      ControlFlowAnalyzer liveAfterSp = new ControlFlowAnalyzer(initialSequenceCfa);
      liveAfterSp.traverseFromRunAsync(runAsync);
      dependencyRecorder.endDependencyGraph();

      LivenessPredicate liveNow = new CfaLivenessPredicate(liveAfterSp);

      Fragment fragment = new Fragment(Fragment.Type.INITIAL, lastInitialFragment);
      fragment.setFragmentId(nextFragmentIdToAssign++);
      fragment.addRunAsync(runAsync);
      List<JsStatement> statements = statementsForFragment(fragment.getFragmentId(),
          alreadyLoaded, liveNow);
      statements.addAll(fragmentExtractor.createOnLoadedCall(fragment.getFragmentId()));
      fragment.setStatements(statements);
      fragments.add(fragment);
      lastInitialFragment = fragment;

      initialFragmentNumberSequence.add(fragment.getFragmentId());
      initialSequenceCfa = liveAfterSp;
    }

    // Set the initial fragment sequence.
    jprogram.setInitialFragmentIdSequence(initialFragmentNumberSequence);

    Collection<Collection<JRunAsync>> groupedNonInitialRunAsyncs =
        groupAsyncsByClassLiteral(Collections2.filter(jprogram.getRunAsyncs(),
            new Predicate<JRunAsync>() {
              @Override
              public boolean apply(JRunAsync jRunAsync) {
                return !isInitial(jRunAsync);
              }
            }
        ));

    // Decide exclusive fragments according to the preselected partitionStrategy.
    Collection<Fragment>  exclusiveFragments =
        partitionStrategy.partitionIntoFragments(logger, initialSequenceCfa,
            groupedNonInitialRunAsyncs);

    Fragment leftOverFragment =
        new Fragment(Fragment.Type.NOT_EXCLUSIVE, lastInitialFragment);


    int firstExclusiveFragmentNumber = nextFragmentIdToAssign;
    // Assign fragment numbers to exclusive fragments.
    for (Fragment fragment : exclusiveFragments) {
      fragment.setFragmentId(nextFragmentIdToAssign++);
      fragment.addImmediateAncestors(leftOverFragment);
    }

    // From here numbers are unchanged,
    // Determine which atoms actually land in each exclusive fragment.
    ExclusivityMap exclusivityMap = computeExclusivityMapWithFixups(exclusiveFragments);

    /*
     * Populate the exclusively live fragments. Each includes everything
     * exclusively live after entry point i.
     */
    for (Fragment fragment : exclusiveFragments) {
      assert fragment.isExclusive();

      LivenessPredicate alreadyLoaded = exclusivityMap.getLivenessPredicate(
          ExclusivityMap.NOT_EXCLUSIVE);
      LivenessPredicate liveNow = exclusivityMap.getLivenessPredicate(fragment);
      List<JsStatement> statements = statementsForFragment(fragment.getFragmentId(),
          alreadyLoaded, liveNow);
      fragment.setStatements(statements);
      fragment.addStatements(
          fragmentExtractor.createOnLoadedCall(fragment.getFragmentId()));
    }

    fragments.addAll(exclusiveFragments);

    /*
     * Populate the leftovers fragment.
     */
    {
      LivenessPredicate alreadyLoaded = new CfaLivenessPredicate(initialSequenceCfa);
      LivenessPredicate liveNow = exclusivityMap.getLivenessPredicate(ExclusivityMap.NOT_EXCLUSIVE);
      leftOverFragment.setFragmentId(nextFragmentIdToAssign++);
      List<JsStatement> statements = statementsForFragment(leftOverFragment.getFragmentId(),
          alreadyLoaded, liveNow);
      statements.addAll(fragmentExtractor.createOnLoadedCall(leftOverFragment.getFragmentId()));
      leftOverFragment.setStatements(statements);
      fragments.add(leftOverFragment);
    }

    // now install the new statements in the program fragments
    jsprogram.setFragmentCount(fragments.size());
    for (int i = 0; i < fragments.size(); i++) {
      JsBlock fragmentBlock = jsprogram.getFragmentBlock(i);
      fragmentBlock.getStatements().clear();
      fragmentBlock.getStatements().addAll(fragments.get(i).getStatements());
    }

    // Pass the fragment partitioning information to JProgram.
    jprogram.setFragmentPartitioningResult(
        new FragmentPartitioningResult(fragments, jprogram.getRunAsyncs().size()));

    // Lastly patch up the JavaScript AST
    replaceFragmentId();
  }

  private boolean isInitial(JRunAsync runAsync) {
    return initialLoadSequence.contains(runAsync);
  }

  /**
   * Patch up the fragment loading code in the JavaScript AST.
   *
   * <p>Initially GWT.runAsyncs are replaced in the {@link ReplaceRunAsyncs} pass and some code
   * is added to the AST that references the fragment for a runAsync. At that stage (before any
   * code splitting has occurred) each unique runAsync id and the number of runAsyncs are embedded
   * in the AST as "tagged" JsNumbericEntry. After code splitting those entries need to be replaced
   * by the frament ids associatied with each runAsync and the total number of fragments.
   * </p>
   */
  private void replaceFragmentId() {
    // TODO(rluble): this approach where the ast is patched  is not very clean. Maybe the fragment
    // information should be data instead of code in the ast.
    final FragmentPartitioningResult result = jprogram.getFragmentPartitioningResult();
    (new JsModVisitor() {
      @Override
      public void endVisit(JsNumericEntry x, JsContext ctx) {
        if (x.getKey().equals("RunAsyncFragmentIndex")) {
          int fragmentId = result.getFragmentForRunAsync(x.getValue());
          x.setValue(fragmentId);
        }
        // this is actually the fragmentId for the leftovers fragment.
        if (x.getKey().equals("RunAsyncFragmentCount")) {
         x.setValue(jsprogram.getFragmentCount() - 1);
        }
      }
    }).accept(jsprogram);
  }
}
