/*
 * Copyright 2009 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.js;

import com.google.gwt.core.ext.BadPropertyValueException;
import com.google.gwt.core.ext.ConfigurationProperty;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsModVisitor;
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.JsVars.JsVar;

import java.util.ArrayList;
import java.util.List;

/**
 * Divides large var statements into smaller ones. Very long var statements have
 * trouble on some browsers, including the initial Safari 4 beta.  See Issue
 * 3455.
 */
public class JsBreakUpLargeVarStatements extends JsModVisitor {
  private static final String CONFIG_PROP_MAX_VARS = "compiler.max.vars.per.var";

  public static void exec(JsProgram program, PropertyOracle[] propertyOracles) {
    (new JsBreakUpLargeVarStatements(propertyOracles)).accept(program);
  }

  private static JsVars last(List<JsVars> list) {
    return list.get(list.size() - 1);
  }

  private final int maxVarsPerStatement;

  private JsBreakUpLargeVarStatements(PropertyOracle[] propertyOracles) {
    maxVarsPerStatement = getMaxVarsPerStatement(propertyOracles[0]);
  }

  @Override
  public void endVisit(JsVars x, JsContext<JsStatement> context) {
    if (maxVarsPerStatement < 0) {
      return;
    }

    if (x.getNumVars() > maxVarsPerStatement) {
      // compute a list of smaller JsVars statements
      List<JsVars> smallerVars = new ArrayList<JsVars>();
      smallerVars.add(makeNewChildVars(x));

      for (JsVar var : x) {
        if (last(smallerVars).getNumVars() >= maxVarsPerStatement) {
          // Previous statement is full; start a new one
          smallerVars.add(makeNewChildVars(x));
        }
        last(smallerVars).add(var);
      }

      // replace x by the sequence smallerVars
      for (JsVars sv : smallerVars) {
        context.insertBefore(sv);
      }
      context.removeMe();
    }
  }

  /**
   * Look up in the specified property oracle the maximum number of variables to
   * allow per var statement.
   */
  private int getMaxVarsPerStatement(PropertyOracle propertyOracle)
      throws InternalCompilerException, NumberFormatException {
    ConfigurationProperty prop;
    try {
      prop = propertyOracle.getConfigurationProperty(CONFIG_PROP_MAX_VARS);
    } catch (BadPropertyValueException e) {
      throw new InternalCompilerException("Could not find property "
          + CONFIG_PROP_MAX_VARS, e);
    }
    int t = Integer.parseInt(prop.getValues().get(0));
    return t;
  }

  /**
   * Make a new, empty {@link JsVars} that is a child of x.
   */
  private JsVars makeNewChildVars(JsVars x) {
    return new JsVars(x.getSourceInfo().makeChild(
        JsBreakUpLargeVarStatements.class,
        "breaking up a large vars statement into smaller ones"));
  }
}
