/*
 * 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.dev.js.ast.JsBlock;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsInvocation;
import com.google.gwt.dev.js.ast.JsModVisitor;
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsNameOf;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsVisitor;
import com.google.gwt.dev.util.collect.IdentityHashSet;

import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

/**
 * Replace references to functions which have post-obfuscation duplicate bodies
 * by reference to a canonical one. Intended to run only when stack trace
 * stripping is enabled.
 */
public class JsDuplicateFunctionRemover {

  private class DuplicateFunctionBodyRecorder extends JsVisitor {

    private final Set<JsName> dontReplace = new IdentityHashSet<JsName>();

    private final Map<JsName, JsName> duplicateOriginalMap = new IdentityHashMap<JsName, JsName>();

    private final Stack<JsNameRef> invocationQualifiers = new Stack<JsNameRef>();

    private final Map<String, JsName> uniqueBodies = new HashMap<String, JsName>();

    public DuplicateFunctionBodyRecorder() {
      // Add sentinel to stop Stack.peek() from throwing exception.
      invocationQualifiers.add(null);
    }

    @Override
    public void endVisit(JsInvocation x, JsContext ctx) {
      if (x.getQualifier() instanceof JsNameRef) {
        invocationQualifiers.pop();
      }
    }

    @Override
    public void endVisit(JsNameOf x, JsContext ctx) {
      dontReplace.add(x.getName());
    }

    @Override
    public void endVisit(JsNameRef x, JsContext ctx) {
      if (x != invocationQualifiers.peek()) {
        if (x.getName() != null) {
          dontReplace.add(x.getName());
        }
      }
    }

    public Set<JsName> getBlacklist() {
      return dontReplace;
    }

    public Map<JsName, JsName> getDuplicateMap() {
      return duplicateOriginalMap;
    }

    @Override
    public boolean visit(JsFunction x, JsContext ctx) {
      /*
       * Don't process anonymous functions.
       */
      if (x.getName() != null) {
        String fnSource = x.toSource();
        String body = fnSource.substring(fnSource.indexOf("("));
        JsName original = uniqueBodies.get(body);
        if (original != null) {
          duplicateOriginalMap.put(x.getName(), original);
        } else {
          uniqueBodies.put(body, x.getName());
        }
      }
      return true;
    }

    @Override
    public boolean visit(JsInvocation x, JsContext ctx) {
      if (x.getQualifier() instanceof JsNameRef) {
        invocationQualifiers.push((JsNameRef) x.getQualifier());
      }
      return true;
    }
  }

  private class ReplaceDuplicateInvocationNameRefs extends JsModVisitor {

    private final Set<JsName> blacklist;

    private final Map<JsName, JsName> duplicateMap;

    public ReplaceDuplicateInvocationNameRefs(Map<JsName, JsName> duplicateMap,
        Set<JsName> blacklist) {
      this.duplicateMap = duplicateMap;
      this.blacklist = blacklist;
    }

    @Override
    public void endVisit(JsNameRef x, JsContext ctx) {
      JsName orig = duplicateMap.get(x.getName());
      if (orig != null && x.getName() != null
          && x.getName().getEnclosing() == program.getScope()
          && !blacklist.contains(x.getName()) && !blacklist.contains(orig)) {
        ctx.replaceMe(orig.makeRef(x.getSourceInfo()));
      }
    }
  }

  // Needed for OptimizerTestBase
  public static boolean exec(JsProgram program) {
    return new JsDuplicateFunctionRemover(program).execImpl(program.getFragmentBlock(0));
  }

  public static boolean exec(JsProgram program, JsBlock fragment) {
    return new JsDuplicateFunctionRemover(program).execImpl(fragment);
  }

  private final JsProgram program;

  public JsDuplicateFunctionRemover(JsProgram program) {
    this.program = program;
  }

  private boolean execImpl(JsBlock fragment) {
    DuplicateFunctionBodyRecorder dfbr = new DuplicateFunctionBodyRecorder();
    dfbr.accept(fragment);
    ReplaceDuplicateInvocationNameRefs rdup = new ReplaceDuplicateInvocationNameRefs(
        dfbr.getDuplicateMap(), dfbr.getBlacklist());
    rdup.accept(fragment);
    return rdup.didChange();
  }
}
