/*
 * 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;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReturnStatement;
import com.google.gwt.dev.jjs.ast.JThisRef;

import java.util.List;

/**
 * Performs optimizations on Enums.
 */
public class EnumNameObfuscator {

  private static class EnumNameCallChecker extends JModVisitor {

    private final JDeclaredType classType;
    private final JMethod enumNameMethod;
    private final JMethod enumToStringMethod;
    private final JDeclaredType enumType;
    private final JMethod enumValueOfMethod;
    private final TreeLogger logger;
    private final JDeclaredType stringType;

    public EnumNameCallChecker(JProgram jprogram, TreeLogger logger) {
      this.logger = logger;
      this.enumNameMethod = jprogram.getIndexedMethod("Enum.name");
      this.enumToStringMethod = jprogram.getIndexedMethod("Enum.toString");
      this.classType = jprogram.getIndexedType("Class");
      this.enumType = jprogram.getIndexedType("Enum");
      this.stringType = jprogram.getIndexedType("String");

      /*
       * Find the correct version of enumValueOfMethod.
       * 
       * Note: it doesn't work to check against a ref returned by
       * jprogram.getIndexedMethod("Enum.valueOf"), since there are 2 different
       * versions of Enum.valueOf in our jre emulation library, and the indexed
       * ref won't reliably flag the public instance, which is the one we want
       * here (i.e. Enum.valueOf(Class<T>,String)). The other version is
       * protected, but is called by the generated constructors for sub-classes
       * of Enum, and we don't want to warn for those cases.
       */
      JMethod foundMethod = null;
      List<JMethod> enumMethods = enumType.getMethods();
      for (JMethod enumMethod : enumMethods) {
        if ("valueOf".equals(enumMethod.getName())) {
          List<JParameter> jParameters = enumMethod.getParams();
          if (jParameters.size() == 2 && jParameters.get(0).getType() == classType
              && jParameters.get(1).getType() == stringType) {
            foundMethod = enumMethod;
            break;
          }
        }
      }
      this.enumValueOfMethod = foundMethod;
    }

    @Override
    public void endVisit(JMethodCall x, Context ctx) {
      JMethod target = x.getTarget();
      JDeclaredType type = target.getEnclosingType();

      if (type instanceof JClassType) {
        JClassType cType = (JClassType) type;

        if (target == enumNameMethod || target == enumToStringMethod || target == enumValueOfMethod) {
          warn(x);
        } else if (cType.isEnumOrSubclass() != null) {
          if ("valueOf".equals(target.getName())) {
            /*
             * Check for calls to the auto-generated
             * EnumSubType.valueOf(String). Note, the check of the signature for
             * the single String arg version is to avoid flagging user-defined
             * overloaded versions of the method, which are presumably ok.
             */
            List<JParameter> jParameters = target.getParams();
            if (jParameters.size() == 1 && jParameters.get(0).getType() == stringType) {
              warn(x);
            }
          }
        }
      }
    }

    @Override
    public boolean visit(JClassType x, Context ctx) {
      if (x == enumType) {
        // don't traverse into Enum class itself, don't warn on internal method
        // calls
        return false;
      }
      return true;
    }

    private void warn(JMethodCall x) {
      /*
       * TODO: add a way to suppress warning with annotation if you know what
       * you're doing.
       */
      logger.log(TreeLogger.WARN, "Call to Enum method " + x.getTarget().getName()
          + " when enum obfuscation is enabled:  " + x.getSourceInfo().getFileName() + ":"
          + x.getSourceInfo().getStartLine());
    }
  }

  private static class EnumNameReplacer extends JModVisitor {

    private final JMethod enumObfuscatedName;
    private final JClassType enumType;
    private final JProgram jprogram;
    private final TreeLogger logger;

    public EnumNameReplacer(JProgram jprogram, TreeLogger logger) {
      this.logger = logger;
      this.jprogram = jprogram;
      this.enumType = (JClassType) jprogram.getIndexedType("Enum");
      this.enumObfuscatedName = jprogram.getIndexedMethod("Enum.obfuscatedName");
    }

    @Override
    public void endVisit(JReturnStatement x, Context ctx) {
      info(x);
      JReturnStatement toReturn =
          new JReturnStatement(x.getSourceInfo(), new JMethodCall(x.getSourceInfo(), new JThisRef(x
              .getSourceInfo(), enumType), enumObfuscatedName));
      ctx.replaceMe(toReturn);
    }

    public void exec() {
      accept(jprogram.getIndexedMethod("Enum.name"));
    }

    private void info(JReturnStatement x) {
      if (logger.isLoggable(TreeLogger.INFO)) {
        logger.log(TreeLogger.INFO, "Replacing Enum.name method :  "
            + x.getSourceInfo().getFileName() + ":"
            + x.getSourceInfo().getStartLine());
      }
    }
  }

  public static void exec(JProgram jprogram, TreeLogger logger) {
    new EnumNameCallChecker(jprogram, logger).accept(jprogram);
    new EnumNameReplacer(jprogram, logger).exec();
  }
}
