/*
 * 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.JsExpression;
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.JsStatement;
import com.google.gwt.dev.js.ast.JsVars;
import com.google.gwt.dev.js.ast.JsVisitor;
import com.google.gwt.dev.js.ast.JsVars.JsVar;

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

/**
 * 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<JsExpression> ctx) {
      JsName name = x.getName();
      if (name != null) {
        definitionSeen(name);
      }
    }

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

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

    @Override
    public boolean visit(JsProgram x, JsContext<JsProgram> 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<JsExpression> 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<JsExpression> ctx) {
      if (namesToPredefine.contains(x.getName())) {
        ctx.replaceMe(makeRefViaJslink(x.getName(), x.getSourceInfo()));
      }
    }

    @Override
    public void endVisit(JsVars x, JsContext<JsStatement> 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 Set<JsName> namesToPredefine = new LinkedHashSet<JsName>();
  private final PropertyOracle[] propertyOracles;
  private final TreeLogger logger;

  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, "defining jslink");
    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;
  }
}
