/*
 * Copyright 2004 The Closure Compiler Authors.
 *
 * 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.javascript.jscomp;

import static com.google.common.base.Preconditions.checkState;

import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.google.javascript.jscomp.AbstractCompiler.LifeCycleStage;
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
import com.google.javascript.rhino.IR;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.annotation.Nullable;

/**
 * Apache Royale copied RenameProperties and modified it to handle
 * Royale modules.
 * 
 * RenameProperties renames properties (including methods) of all JavaScript
 * objects. This includes prototypes, functions, object literals, etc.
 *
 * <p> If provided a VariableMap of previously used names, it tries to reuse
 * those names.
 *
 * <p> To prevent a property from getting renamed you may extern it (add it to
 * your externs file) or put it in quotes.
 *
 * <p> To avoid run-time JavaScript errors, use quotes when accessing properties
 * that are defined using quotes.
 *
 * <pre>
 *   var a = {'myprop': 0}, b = a['myprop'];  // correct
 *   var x = {'myprop': 0}, y = x.myprop;     // incorrect
 * </pre>
 *
 * This pass also recognizes and replaces special renaming functions. They supply
 * a property name as the string literal for the first argument.
 * This pass will replace them as though they were JS property
 * references. Here are two examples:
 *    JSCompiler_renameProperty('propertyName') -> 'jYq'
 *    JSCompiler_renameProperty('myProp.nestedProp.innerProp') -> 'e4.sW.C$'
 *
 */
class RenamePropertiesWithModuleSupport implements CompilerPass {
  private static final Splitter DOT_SPLITTER = Splitter.on('.');

  private final AbstractCompiler compiler;
  private final boolean generatePseudoNames;

  /** Property renaming map from a previous compilation. */
  private final VariableMap prevUsedPropertyMap;
  
  /** Original names of properties that were renamed */
  private final List<String> prevUsedPropertyOldNames = new ArrayList<String>();

  private final List<Node> toRemove = new ArrayList<Node>();
  private final List<Node> stringNodesToRename = new ArrayList<Node>();
  private final Map<Node, Node> callNodeToParentMap =
      new LinkedHashMap<Node, Node>();
  private final char[] reservedFirstCharacters;
  private final char[] reservedNonFirstCharacters;

  // Map from property name to Property object
  private final Map<String, Property> propertyMap = new LinkedHashMap<String, Property>();

  // Property names that don't get renamed
  private final Set<String> externedNames = new LinkedHashSet<String>(
      Arrays.asList("prototype"));

  // Names to which properties shouldn't be renamed, to avoid name conflicts
  private final Set<String> quotedNames = new LinkedHashSet<String>();

  // Shared name generator
  private final NameGenerator nameGenerator;

  private static final Comparator<Property> FREQUENCY_COMPARATOR =
    new Comparator<Property>() {
      @Override
      public int compare(Property p1, Property p2) {

        /**
         * First a frequently used names would always be picked first.
         */
        if (p1.numOccurrences != p2.numOccurrences) {
          return p2.numOccurrences - p1.numOccurrences;
        }

        /**
         * Finally, for determinism, we compare them based on the old name.
         */
        return p1.oldName.compareTo(p2.oldName);
       }
    };

  static final DiagnosticType BAD_CALL = DiagnosticType.error(
      "JSC_BAD_RENAME_PROPERTY_FUNCTION_NAME_CALL",
      "Bad {0} call - the first argument must be a string literal");

  static final DiagnosticType BAD_ARG = DiagnosticType.error(
      "JSC_BAD_RENAME_PROPERTY_FUNCTION_NAME_ARG",
      "Bad {0} argument - ''{1}'' is not a valid JavaScript identifier");

  /**
   * Creates an instance.
   *
   * @param compiler The JSCompiler
   * @param generatePseudoNames Generate pseudo names. e.g foo -> $foo$ instead
   *        of compact obfuscated names. This is used for debugging.
   * @param nameGenerator a shared NameGenerator that this instance can use;
   *        the instance may reset or reconfigure it, so the caller should
   *        not expect any state to be preserved
   */
  RenamePropertiesWithModuleSupport(AbstractCompiler compiler, boolean generatePseudoNames,
      NameGenerator nameGenerator) {
    this(compiler, generatePseudoNames, null, null, null, nameGenerator);
  }

  /**
   * Creates an instance.
   *
   * @param compiler The JSCompiler.
   * @param generatePseudoNames Generate pseudo names. e.g foo -> $foo$ instead
   *        of compact obfuscated names. This is used for debugging.
   * @param prevUsedPropertyMap The property renaming map used in a previous
   *        compilation.
   * @param nameGenerator a shared NameGenerator that this instance can use;
   *        the instance may reset or reconfigure it, so the caller should
   *        not expect any state to be preserved
   */
  RenamePropertiesWithModuleSupport(AbstractCompiler compiler,
      boolean generatePseudoNames, VariableMap prevUsedPropertyMap,
      NameGenerator nameGenerator) {
    this(compiler, generatePseudoNames, prevUsedPropertyMap, null, null, nameGenerator);
  }

  /**
   * Creates an instance.
   *
   * @param compiler The JSCompiler.
   * @param generatePseudoNames Generate pseudo names. e.g foo -> $foo$ instead of compact
   *     obfuscated names. This is used for debugging.
   * @param prevUsedPropertyMap The property renaming map used in a previous compilation.
   * @param reservedFirstCharacters If specified these characters won't be used in generated names
   *     for the first character
   * @param reservedNonFirstCharacters If specified these characters won't be used in generated
   *     names for characters after the first
   * @param nameGenerator a shared NameGenerator that this instance can use; the instance may reset
   *     or reconfigure it, so the caller should not expect any state to be preserved
   */
  RenamePropertiesWithModuleSupport(
      AbstractCompiler compiler,
      boolean generatePseudoNames,
      VariableMap prevUsedPropertyMap,
      @Nullable char[] reservedFirstCharacters,
      @Nullable char[] reservedNonFirstCharacters,
      NameGenerator nameGenerator) {
    this.compiler = compiler;
    this.generatePseudoNames = generatePseudoNames;
    this.prevUsedPropertyMap = prevUsedPropertyMap;
    this.reservedFirstCharacters = reservedFirstCharacters;
    this.reservedNonFirstCharacters = reservedNonFirstCharacters;
    this.nameGenerator = nameGenerator;
    externedNames.addAll(compiler.getExternProperties());
  }

  @Override
  public void process(Node externs, Node root) {
    checkState(compiler.getLifeCycleStage().isNormalized());

    if (prevUsedPropertyMap != null) {
    	prevUsedPropertyOldNames.addAll(prevUsedPropertyMap.getOriginalNameToNewNameMap().keySet());
    }
    
    NodeTraversal.traverse(compiler, root, new ProcessProperties());

    Set<String> reservedNames =
        Sets.newHashSetWithExpectedSize(externedNames.size() + quotedNames.size());

    // Assign names, sorted by descending frequency to minimize code size.
    Set<Property> propsByFreq = new TreeSet<Property>(FREQUENCY_COMPARATOR);
    propsByFreq.addAll(propertyMap.values());

    // First, try and reuse as many property names from the previous compilation
    // as possible.
    if (prevUsedPropertyMap != null) {
      reusePropertyNames(reservedNames, propsByFreq);
    }

    /* add externed and quoted names after previously renamed
     * properties are told to re-use their renames from the main
     * app.  The original code added these names before
     * trying to reuse previous renames because those
     * externs are typically from 3rd-party libraries, but
     * in modules, externs are from the main loading app
     * and we want to reuse previous renames as much as possible
     * because classes in the main loading app will make calls
     * using the renames instead of the exported name so any
     * override or implementations of interface methods must
     * also have the same rename.
     */
    reservedNames.addAll(externedNames);
    reservedNames.addAll(quotedNames);
    
    generateNames(propsByFreq, reservedNames);

    // Update the string nodes.
    for (Node n : stringNodesToRename) {
      String oldName = n.getString();
      Property p = propertyMap.get(oldName);
      if (p != null && p.newName != null) {
        checkState(oldName.equals(p.oldName));
        n.setString(p.newName);
        if (!p.newName.equals(oldName)) {
          compiler.reportChangeToEnclosingScope(n);
        }
      }
    }

    // Update the call nodes.
    for (Map.Entry<Node, Node> nodeEntry : callNodeToParentMap.entrySet()) {
      Node parent = nodeEntry.getValue();
      Node firstArg = nodeEntry.getKey().getSecondChild();
      StringBuilder sb = new StringBuilder();
      for (String oldName : DOT_SPLITTER.split(firstArg.getString())) {
        Property p = propertyMap.get(oldName);
        String replacement;
        if (p != null && p.newName != null) {
          checkState(oldName.equals(p.oldName));
          replacement = p.newName;
        } else {
          replacement = oldName;
        }
        if (sb.length() > 0) {
          sb.append('.');
        }
        sb.append(replacement);
      }
      parent.replaceChild(nodeEntry.getKey(), IR.string(sb.toString()));
      compiler.reportChangeToEnclosingScope(parent);
    }

    // Complete queued removals.
    for (Node n : toRemove) {
      Node parent = n.getParent();
      compiler.reportChangeToEnclosingScope(n);
      n.detach();
      NodeUtil.markFunctionsDeleted(n, compiler);
      if (!parent.hasChildren() && !parent.isScript()) {
        parent.detach();
      }
    }

    compiler.setLifeCycleStage(LifeCycleStage.NORMALIZED_OBFUSCATED);
    // This pass may rename getter or setter properties
    GatherGettersAndSetterProperties.update(compiler, externs, root);
  }

  /**
   * Runs through the list of properties and renames as many as possible with
   * names from the previous compilation. Also, updates reservedNames with the
   * set of reused names.
   * @param reservedNames Reserved names to use during renaming.
   * @param allProps Properties to rename.
   */
  private void reusePropertyNames(Set<String> reservedNames,
                                  Collection<Property> allProps) {
    for (Property prop : allProps) {
      // Check if this node can reuse a name from a previous compilation - if
      // it can set the newName for the property too.
      String prevName = prevUsedPropertyMap.lookupNewName(prop.oldName);
      if (!generatePseudoNames && prevName != null) {
        // We can reuse prevName if it's not reserved.
        if (reservedNames.contains(prevName)) {
          continue;
        }

        prop.newName = prevName;
        reservedNames.add(prevName);
      }
    }
  }

  /**
   * Generates new names for properties.
   *
   * @param props Properties to generate new names for
   * @param reservedNames A set of names to which properties should not be
   *     renamed
   */
  private void generateNames(Set<Property> props, Set<String> reservedNames) {
    nameGenerator.reset(reservedNames, "", reservedFirstCharacters, reservedNonFirstCharacters);
    for (Property p : props) {
      if (generatePseudoNames) {
        p.newName = "$" + p.oldName + "$";
      } else {
        // If we haven't already given this property a reusable name.
        if (p.newName == null) {
          p.newName = nameGenerator.generateNextName();
        }
      }
      reservedNames.add(p.newName);
    }
  }

  /**
   * Gets the property renaming map (the "answer key").
   *
   * @return A mapping from original names to new names
   */
  VariableMap getPropertyMap() {
    ImmutableMap.Builder<String, String> map = ImmutableMap.builder();
    for (Property p : propertyMap.values()) {
      if (p.newName != null) {
        map.put(p.oldName, p.newName);
      }
    }
    return new VariableMap(map.build());
  }


  // -------------------------------------------------------------------------

  /**
   * A traversal callback that collects property names and counts how
   * frequently each property name occurs.
   */
  private class ProcessProperties extends AbstractPostOrderCallback {

    @Override
    public void visit(NodeTraversal t, Node n, Node parent) {
      switch (n.getToken()) {
        case COMPUTED_PROP:
          break;
        case GETPROP:
          Node propNode = n.getSecondChild();
          if (propNode.isString()) {
            if (compiler.getCodingConvention().blockRenamingForProperty(
                propNode.getString())) {
              externedNames.add(propNode.getString());
              break;
            }
            maybeMarkCandidate(propNode);
          }
          break;
        case OBJECTLIT:
          for (Node key = n.getFirstChild(); key != null; key = key.getNext()) {
            if (key.isComputedProp()) {
              // We don't want to rename computed properties
              continue;
            } else if (key.isQuotedString()) {
              // Ensure that we never rename some other property in a way
              // that could conflict with this quoted key.
              quotedNames.add(key.getString());
            } else if (compiler.getCodingConvention().blockRenamingForProperty(key.getString())) {
              externedNames.add(key.getString());
            } else {
              maybeMarkCandidate(key);
            }
          }
          break;
        case OBJECT_PATTERN:
          // Iterate through all the nodes in the object pattern
          for (Node key = n.getFirstChild(); key != null; key = key.getNext()) {
            if (key.isComputedProp()) {
              // We don't want to rename computed properties
              continue;
            } else if (key.isQuotedString()) {
              // Ensure that we never rename some other property in a way
              // that could conflict with this quoted key.
              quotedNames.add(key.getString());
            } else if (compiler.getCodingConvention().blockRenamingForProperty(key.getString())) {
              externedNames.add(key.getString());
            } else {
              maybeMarkCandidate(key);
            }
          }
          break;
        case GETELEM:
          // If this is a quoted property access (e.g. x['myprop']), we need to
          // ensure that we never rename some other property in a way that
          // could conflict with this quoted name.
          Node child = n.getLastChild();
          if (child != null && child.isString()) {
            quotedNames.add(child.getString());
          }
          break;
        case CALL: {
          // We replace property renaming function calls with a string
          // containing the renamed property.
          Node fnName = n.getFirstChild();
          if (compiler
              .getCodingConvention()
              .isPropertyRenameFunction(fnName.getOriginalQualifiedName())) {
            callNodeToParentMap.put(n, parent);
            countCallCandidates(t, n);
          }
          break;
        }
        case CLASS_MEMBERS:
          {
            // Replace function names defined in a class scope
            for (Node key = n.getFirstChild(); key != null; key = key.getNext()) {
              if (key.isComputedProp()) {
                // We don't want to rename computed properties.
                continue;
              } else {
                Node member = key.getFirstChild();

                String memberDefName = key.getString();
                if (member.isFunction()) {
                  Node fnName = member.getFirstChild();
                  if (compiler.getCodingConvention().blockRenamingForProperty(memberDefName)) {
                    externedNames.add(fnName.getString());
                  } else if (memberDefName.equals("constructor")
                      || memberDefName.equals("superClass_")) {
                    // TODO (simarora) is there a better way to identify these externs?
                    externedNames.add(fnName.getString());
                  } else {
                    maybeMarkCandidate(key);
                  }
                }
              }
            }
            break;
          }
        case FUNCTION:
          {
            // We eliminate any stub implementations of JSCompiler_renameProperty
            // that we encounter.
            if (NodeUtil.isFunctionDeclaration(n)) {
              String name = n.getFirstChild().getString();
              if (NodeUtil.JSC_PROPERTY_NAME_FN.equals(name)) {
                toRemove.add(n);
              }
            } else if (parent.isName()
                && NodeUtil.JSC_PROPERTY_NAME_FN.equals(parent.getString())) {
              Node varNode = parent.getParent();
              if (varNode.isVar()) {
                toRemove.add(parent);
              }
            } else if (NodeUtil.isFunctionExpression(n)
                && parent.isAssign()
                && parent.getFirstChild().isGetProp()
                && compiler
                    .getCodingConvention()
                    .isPropertyRenameFunction(parent.getFirstChild().getOriginalQualifiedName())) {
              Node exprResult = parent.getParent();
              if (exprResult.isExprResult()
                  && NodeUtil.isStatementBlock(exprResult.getParent())
                  && exprResult.getFirstChild().isAssign()) {
                toRemove.add(exprResult);
              }
            }
            break;
          }
        default:
          break;
      }
    }

    /**
     * If a property node is eligible for renaming, stashes a reference to it
     * and increments the property name's access count.
     *
     * @param n The STRING node for a property
     */
    private void maybeMarkCandidate(Node n) {
      String name = n.getString();
      if (!externedNames.contains(name) || prevUsedPropertyOldNames.contains(name)) {
        stringNodesToRename.add(n);
        countPropertyOccurrence(name);
      }
    }

    /**
     * Counts references to property names that occur in a special function
     * call.
     *
     * @param callNode The CALL node for a property
     * @param t The traversal
     */
    private void countCallCandidates(NodeTraversal t, Node callNode) {
      String fnName = callNode.getFirstChild().getOriginalName();
      if (fnName == null) {
        fnName = callNode.getFirstChild().getString();
      }
      Node firstArg = callNode.getSecondChild();
      if (!firstArg.isString()) {
        t.report(callNode, BAD_CALL, fnName);
        return;
      }

      for (String name : DOT_SPLITTER.split(firstArg.getString())) {
        if (!TokenStream.isJSIdentifier(name)) {
          t.report(callNode, BAD_ARG, fnName);
          continue;
        }
        if (!externedNames.contains(name) || prevUsedPropertyOldNames.contains(name)) {
          countPropertyOccurrence(name);
        }
      }
    }

    /**
     * Increments the occurrence count for a property name.
     *
     * @param name The property name
     */
    private void countPropertyOccurrence(String name) {
      Property prop = propertyMap.get(name);
      if (prop == null) {
        prop = new Property(name);
        propertyMap.put(name, prop);
      }
      prop.numOccurrences++;
    }
  }

  // -------------------------------------------------------------------------

  /**
   * Encapsulates the information needed for renaming a property.
   */
  private static class Property {
    final String oldName;
    String newName;
    int numOccurrences;

    Property(String name) {
      this.oldName = name;
    }
  }
}
