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

import com.google.gwt.core.ext.BadPropertyValueException;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.js.ast.JsBinaryOperation;
import com.google.gwt.dev.js.ast.JsBinaryOperator;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsModVisitor;
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsVars;
import com.google.gwt.dev.js.ast.JsVars.JsVar;
import com.google.gwt.dev.js.ast.JsVisitor;

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Rewrite JavaScript to better handle references from one code fragment to
 * another. For any function defined off the initial download and accessed from
 * a different island than the one it's defined on, predefine a variable in the
 * initial download to hold its definition.
 */
public class HandleCrossFragmentReferences {
  /**
   * Find out which islands define and use each named function or variable. This
   * visitor is not smart about which definitions and uses matter. It blindly
   * records all of them.
   */
  private class FindNameReferences extends JsVisitor {
    Map<JsName, Set<Integer>> islandsDefining = new LinkedHashMap<JsName, Set<Integer>>();
    Map<JsName, Set<Integer>> islandsUsing = new LinkedHashMap<JsName, Set<Integer>>();
    private int currentIsland;

    @Override
    public void endVisit(JsFunction x, JsContext ctx) {
      JsName name = x.getName();
      if (name != null) {
        definitionSeen(name);
      }
    }

    @Override
    public void endVisit(JsNameRef x, JsContext ctx) {
      if (x.getQualifier() == null) {
        JsName name = x.getName();
        if (name != null) {
          referenceSeen(name);
        }
      }
    }

    @Override
    public void endVisit(JsVars x, JsContext ctx) {
      for (JsVar var : x) {
        JsName name = var.getName();
        if (name != null) {
          definitionSeen(name);
        }
      }
    }

    @Override
    public boolean visit(JsProgram x, JsContext ctx) {
      for (int i = 0; i < x.getFragmentCount(); i++) {
        currentIsland = i;
        accept(x.getFragmentBlock(i));
      }

      return false;
    }

    private void definitionSeen(JsName name) {
      /*
       * Support multiple definitions, because local variables can reuse the
       * same name.
       */
      Set<Integer> defs = islandsDefining.get(name);
      if (defs == null) {
        defs = new LinkedHashSet<Integer>();
        islandsDefining.put(name, defs);
      }
      defs.add(currentIsland);
    }

    private void referenceSeen(JsName name) {
      Set<Integer> refs = islandsUsing.get(name);
      if (refs == null) {
        refs = new HashSet<Integer>();
        islandsUsing.put(name, refs);
      }
      refs.add(currentIsland);
    }
  }

  /**
   * Rewrite var and function declarations as assignments, if their name is
   * accessed cross-island. Rewrite refs to such names correspondingly.
   */
  private class RewriteDeclsAndRefs extends JsModVisitor {
    @Override
    public void endVisit(JsFunction x, JsContext ctx) {
      if (namesToPredefine.contains(x.getName())) {
        JsBinaryOperation asg =
            new JsBinaryOperation(x.getSourceInfo(), JsBinaryOperator.ASG, makeRefViaJslink(x
                .getName(), x.getSourceInfo()), x);
        x.setName(null);
        ctx.replaceMe(asg);
      }
    }

    @Override
    public void endVisit(JsNameRef x, JsContext ctx) {
      if (namesToPredefine.contains(x.getName())) {
        ctx.replaceMe(makeRefViaJslink(x.getName(), x.getSourceInfo()));
      }
    }

    @Override
    public void endVisit(JsVars x, JsContext ctx) {
      if (!ctx.canInsert()) {
        return;
      }

      /*
       * Loop through each var and see if it was predefined. If so, then remove
       * the var. If the var has an initializer, then add back an assignment
       * statement to initialize it. If there is no initializer, then don't add
       * anything back; the var will still have undefined as its initial value,
       * just like before.
       * 
       * A complication is that the variables that are predefined might be
       * interspersed with variables that are not. That means the general result
       * of this transformation has alternating var lists and assignment
       * statements. The currentVar variable holds the most recently inserted
       * statement, if that statement was a JsVars; otherwise it holds null.
       */

      JsVars currentVar = null;
      Iterator<JsVar> varsIterator = x.iterator();
      while (varsIterator.hasNext()) {
        JsVar var = varsIterator.next();
        if (namesToPredefine.contains(var.getName())) {
          // The var was predefined
          if (var.getInitExpr() != null) {
            // If it has an initializer, add an assignment statement
            JsBinaryOperation asg =
                new JsBinaryOperation(var.getSourceInfo(), JsBinaryOperator.ASG, makeRefViaJslink(
                    var.getName(), var.getSourceInfo()), var.getInitExpr());
            ctx.insertBefore(asg.makeStmt());
            currentVar = null;
          }
        } else {
          // The var was not predefined; add it to a var list
          if (currentVar == null) {
            currentVar = new JsVars(x.getSourceInfo());
            ctx.insertBefore(currentVar);
          }
          currentVar.add(var);
        }
      }

      ctx.removeMe();
    }

    private JsNameRef makeRefViaJslink(JsName name, SourceInfo sourceInfo) {
      JsNameRef ref = name.makeRef(sourceInfo);
      ref.setQualifier(jslink.makeRef(sourceInfo));
      return ref;
    }
  }

  public static String PROP_PREDECLARE_VARS = "compiler.predeclare.cross.fragment.references";

  public static void exec(TreeLogger logger, JsProgram jsProgram, PropertyOracle[] propertyOracles) {
    new HandleCrossFragmentReferences(logger, jsProgram, propertyOracles).execImpl();
  }

  private static boolean containsOtherThan(Set<Integer> set, int allowed) {
    for (int elem : set) {
      if (elem != allowed) {
        return true;
      }
    }
    return false;
  }

  private JsName jslink;
  private final JsProgram jsProgram;
  private final TreeLogger logger;
  private final Set<JsName> namesToPredefine = new LinkedHashSet<JsName>();
  private final PropertyOracle[] propertyOracles;

  private HandleCrossFragmentReferences(TreeLogger logger, JsProgram jsProgram,
      PropertyOracle[] propertyOracles) {
    this.logger = logger;
    this.jsProgram = jsProgram;
    this.propertyOracles = propertyOracles;
  }

  private void chooseNamesToPredefine(Map<JsName, Set<Integer>> map,
      Map<JsName, Set<Integer>> islandsUsing) {
    for (Entry<JsName, Set<Integer>> entry : map.entrySet()) {
      JsName name = entry.getKey();
      Set<Integer> defIslands = entry.getValue();
      if (defIslands.size() != 1) {
        // Only rewrite global variables, which should have exactly one
        // definition
        continue;
      }
      int defIsland = defIslands.iterator().next();
      if (defIsland == 0) {
        // Variables defined on the base island can be accessed directly from
        // other islands
        continue;
      }
      Set<Integer> useIslands = islandsUsing.get(name);
      if (useIslands == null) {
        // The variable is never used. Leave it alone.
        continue;
      }

      if (containsOtherThan(islandsUsing.get(name), defIsland)) {
        namesToPredefine.add(name);
      }
    }
  }

  /**
   * Define the jslink object that will be used to fix up cross-island
   * references.
   */
  private void defineJsLink() {
    SourceInfo info = jsProgram.createSourceInfoSynthetic(HandleCrossFragmentReferences.class);
    jslink = jsProgram.getScope().declareName("jslink");
    JsVars vars = new JsVars(info);
    JsVar var = new JsVar(info, jslink);
    var.setInitExpr(new JsObjectLiteral(info));
    vars.add(var);
    jsProgram.getFragmentBlock(0).getStatements().add(0, vars);
  }

  private void execImpl() {
    if (jsProgram.getFragmentCount() == 1) {
      return;
    }
    if (!shouldPredeclareReferences()) {
      return;
    }
    defineJsLink();
    FindNameReferences findNameReferences = new FindNameReferences();
    findNameReferences.accept(jsProgram);
    chooseNamesToPredefine(findNameReferences.islandsDefining, findNameReferences.islandsUsing);
    new RewriteDeclsAndRefs().accept(jsProgram);
  }

  /**
   * Check the property oracles for whether references should be predeclared or
   * not. If any of them say yes, then do the rewrite.
   */
  private boolean shouldPredeclareReferences() {
    for (PropertyOracle props : propertyOracles) {
      try {
        String propValue =
            props.getSelectionProperty(logger, PROP_PREDECLARE_VARS).getCurrentValue();
        if (Boolean.parseBoolean(propValue)) {
          return true;
        }
      } catch (BadPropertyValueException e) {
        // Property not defined; don't rewrite
      }
    }

    return false;
  }
}
