/*
 * Copyright 2014 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.javac;

import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.util.Name.InternalName;
import com.google.gwt.thirdparty.guava.common.base.Function;
import com.google.gwt.thirdparty.guava.common.base.Joiner;
import com.google.gwt.thirdparty.guava.common.base.Predicate;
import com.google.gwt.thirdparty.guava.common.base.Strings;
import com.google.gwt.thirdparty.guava.common.collect.FluentIterable;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.thirdparty.guava.common.collect.Iterables;
import com.google.gwt.thirdparty.guava.common.collect.Lists;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
import org.eclipse.jdt.internal.compiler.impl.StringConstant;
import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.NestedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * Utility functions to interact with JDT classes.
 */
public final class JdtUtil {
  private static final String JSO_CLASS = "com/google/gwt/core/client/JavaScriptObject";

  /**
   * Returns a source name from an array of names.
   */
  public static String asDottedString(char[][] name) {
    return join(name, ".");
  }

  /**
   * Returns a string name from an array of names using {@code separator}.
   */
  public static String join(char[][] name, String separator) {
    StringBuilder result = new StringBuilder();
    if (name.length > 0) {
      result.append(name[0]);
    }

    for (int i = 1; i < name.length; ++i) {
      result.append(separator);
      result.append(name[i]);
    }
    return result.toString();
  }

  /**
   * Returns the fully qualified source name of the type (class, interface or enum) from reference
   * binding.
   * <p>
   * JDT Core (at least 3.11.0.v20150407) returns <code>$Local$</code> synthetic name for local
   * classes.<br>
   * This method aware about local classes and instead of <code>$Local$</code> synthetic name
   * returns fully qualified name of the local class in form of anonymous class (e.g.
   * <code>test.Class1$2</code>).
   * </p>
   */
  public static String getQualifiedSourceName(ReferenceBinding binding) {
    if (binding instanceof LocalTypeBinding) {
      // Using here constantPoolName() instead of coumpoundName due JDT not computing the
      // right compoundName for lambdas inside local class.
      return InternalName.toBinaryName(String.valueOf(binding.constantPoolName()));
    }

    return asDottedString(binding.compoundName);
  }

  /**
   * Returns the top type of the compilation unit that defines
   * {@code binding}.
   */
  public static String getDefiningCompilationUnitType(ReferenceBinding binding) {
    // Get the compilation unit type name.
    // TODO(rluble): check that this is valid for classes declared in the same compilation unit
    // top scope.
    return asDottedString(binding.outermostEnclosingType().compoundName);
  }

  public static String getSourceName(TypeBinding classBinding) {
    return getSourceName(CharOperation.charToString(classBinding.qualifiedPackageName()),
        CharOperation.charToString(classBinding.qualifiedSourceName()));
  }

  public static String getSourceName(String qualifiedPackageName, String qualifiedSourceName) {
    return Joiner.on(".").skipNulls().join(new String[] {
        Strings.emptyToNull(qualifiedPackageName),
        qualifiedSourceName});
  }

  public static String getBinaryName(TypeBinding classBinding) {
    return getBinaryName(CharOperation.charToString(classBinding.qualifiedPackageName()),
        CharOperation.charToString(classBinding.qualifiedSourceName()));
  }

  public static String getBinaryName(String qualifiedPackageName, String qualifiedSourceName) {
    return Joiner.on(".").skipNulls().join(new String[] {
        Strings.emptyToNull(qualifiedPackageName),
        qualifiedSourceName.replace('.','$')});
  }

  public static boolean isInnerClass(ReferenceBinding binding) {
    return binding.isNestedType() && !binding.isStatic();
  }

  /**
   * Get a readable method description from {@code methodBinding} conforming with JSNI formatting.
   * <p>
   * See examples:
   * <ul>
   * <li>a constructor of class A with a java.lang.String parameter will be formatted as
   * "new(Ljava/lang/String;).</li>
   * <li>a method with name m with an parameter of class java.lang.Object and return type boolean
   * will be formatted as "m(Ljava/lang/Object;</li>
   * </ul>,
   */
  public static String formatMethodSignature(MethodBinding methodBinding) {
    ReferenceBinding declaringClassBinding = methodBinding.declaringClass;
    StringBuilder methodNameWithSignature = new StringBuilder();
    String methodName = String.valueOf(methodBinding.selector);
    List<TypeBinding> parameterTypeBindings = Lists.newArrayList();
    if (methodName.equals("<init>")) {
      // It is a constructor.
      // (1) use the JSNI methodName instead of <init>.
      methodName = "new";
      // (2) add the implicit constructor parameters types for non static inner classes.
      if (isInnerClass(declaringClassBinding)) {
        NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClassBinding;
        if (nestedBinding.enclosingInstances != null) {
          for (SyntheticArgumentBinding argumentBinding : nestedBinding.enclosingInstances) {
            parameterTypeBindings.add(argumentBinding.type);
          }
        }
      }
    }

    parameterTypeBindings.addAll(Arrays.asList(methodBinding.parameters));
    methodNameWithSignature.append(methodName);
    methodNameWithSignature.append("(");
    for (TypeBinding parameterTypeBinding : parameterTypeBindings) {
      methodNameWithSignature.append(parameterTypeBinding.signature());
    }
    methodNameWithSignature.append(")");
    return methodNameWithSignature.toString();
  }

  public static String formatBinding(MethodBinding methodBinding) {
    String accessModifier = null;
    if (methodBinding.isProtected()) {
      accessModifier = "protected";
    } else if (methodBinding.isPrivate()) {
      accessModifier = "private";
    } else if (methodBinding.isPublic()) {
      accessModifier = "public";
    }
    return Joiner.on(" ").skipNulls().join(
        accessModifier,
        methodBinding.isStatic() ? "static" : null,
        getSourceName(methodBinding.declaringClass) + "." +
            formatMethodSignature(methodBinding)
    );
  }

  private JdtUtil() {
  }

  public static String getAnnotationParameterString(
      AnnotationBinding annotationBinding, String parameterName) {
    if (annotationBinding != null) {
      for (ElementValuePair parameterNameValuePair : annotationBinding.getElementValuePairs()) {
        if (parameterNameValuePair.getValue() instanceof StringConstant &&
            parameterName.equals(String.valueOf(parameterNameValuePair.getName()))) {
          return ((StringConstant) parameterNameValuePair.getValue()).stringValue();
        }
      }
    }
    return null;
  }

  public static boolean getAnnotationParameterBoolean(
      AnnotationBinding annotationBinding, String parameterName, boolean defaultValue) {
    Boolean booleanParameterValue = getAnnotationParameterBoolean(annotationBinding, parameterName);
    return booleanParameterValue == null ? defaultValue : booleanParameterValue;
  }

  public static Boolean getAnnotationParameterBoolean(
      AnnotationBinding annotationBinding, String parameterName) {
    if (annotationBinding != null) {
      for (ElementValuePair parameterNameValuePair : annotationBinding.getElementValuePairs()) {
        if (parameterNameValuePair.getValue() instanceof BooleanConstant &&
            parameterName.equals(String.valueOf(parameterNameValuePair.getName()))) {
          return ((BooleanConstant) parameterNameValuePair.getValue()).booleanValue();
        }
      }
    }
    return null;
  }

  public static AnnotationBinding getAnnotationByName(Annotation[] annotations, String name) {
    if (annotations == null) {
      return null;
    }
    for (Annotation annotation : annotations) {
      AnnotationBinding annotationBinding = annotation.getCompilerAnnotation();
      if (matchAnnotationName(annotationBinding, name)) {
        return annotationBinding;
      }
    }
    return null;
  }

  public static AnnotationBinding getAnnotationByName(
      AnnotationBinding[] annotationsBindings, String name) {
    if (annotationsBindings == null) {
      return null;
    }
    for (AnnotationBinding annotationBinding : annotationsBindings) {
      if (matchAnnotationName(annotationBinding, name)) {
        return annotationBinding;
      }
    }
    return null;
  }

  private static boolean matchAnnotationName(AnnotationBinding annotationBinding, String name) {
    if (annotationBinding == null) {
      return false;
    }
    return name.equals(CharOperation.toString(annotationBinding.getAnnotationType().compoundName));
  }

  public static TypeBinding getAnnotationParameterTypeBinding(
      AnnotationBinding annotationBinding, String parameterName) {
    if (annotationBinding != null) {
      for (ElementValuePair parameterNameValuePair : annotationBinding.getElementValuePairs()) {
        if (parameterNameValuePair.getValue() instanceof Class &&
            parameterName.equals(String.valueOf(parameterNameValuePair.getName()))) {
          return (TypeBinding) parameterNameValuePair.getValue();
        }
      }
    }
    return null;
  }

  public static TypeBinding[] getAnnotationParameterTypeBindingArray(
      AnnotationBinding annotationBinding, String parameterName) {
    if (annotationBinding == null) {
      return null;
    }

    for (ElementValuePair parameterNameValuePair : annotationBinding.getElementValuePairs()) {
      Object value = parameterNameValuePair.getValue();
      if (!parameterName.equals(String.valueOf(parameterNameValuePair.getName()))) {
        continue;
      }
      if (value instanceof Object[]) {
        Object[] values = (Object[]) value;
        TypeBinding bindings[] = new TypeBinding[values.length];
        System.arraycopy(values, 0, bindings, 0, values.length);
        return bindings;
      }
      assert value instanceof TypeBinding;
      return new TypeBinding[] {(TypeBinding) value};
    }
    return null;
  }

  public static StringConstant[] getAnnotationParameterStringConstantArray(
      AnnotationBinding annotationBinding, String parameterName) {
    if (annotationBinding == null) {
      return null;
    }
    for (ElementValuePair parameterNameValuePair : annotationBinding.getElementValuePairs()) {
      if (!parameterName.equals(String.valueOf(parameterNameValuePair.getName()))) {
        continue;
      }
      Object value = parameterNameValuePair.getValue();
      if (value instanceof Object[]) {
        Object[] values = (Object[]) value;
        StringConstant[] stringConstants = new StringConstant[values.length];
        System.arraycopy(values, 0, stringConstants, 0, values.length);
        return stringConstants;
      }
      assert value instanceof StringConstant;
      return new StringConstant[] {(StringConstant) value};
    }
    return null;
  }

  public static Set<String> getSuppressedWarnings(Annotation[] annotations) {
    if (annotations == null) {
      return ImmutableSet.of();
    }
    AnnotationBinding suppressWarnings =
        getAnnotationByName(annotations, SuppressWarnings.class.getName());
    if (suppressWarnings != null) {
      StringConstant[] values =
          JdtUtil.getAnnotationParameterStringConstantArray(suppressWarnings, "value");
      return FluentIterable.from(Arrays.asList(values))
          .transform(new Function<StringConstant, String>() {
            @Override
            public String apply(StringConstant value) {
              return value.stringValue();
            }
          })
          .toSet();
    }
    return ImmutableSet.of();
  }

  public static String signature(FieldBinding binding) {
    StringBuilder sb = new StringBuilder();
    sb.append(binding.declaringClass.constantPoolName());
    sb.append('.');
    sb.append(binding.name);
    sb.append(':');
    sb.append(binding.type.signature());
    return sb.toString();
  }

  public static String signature(MethodBinding binding) {
    StringBuilder sb = new StringBuilder();
    sb.append(binding.declaringClass.constantPoolName());
    sb.append('.');
    sb.append(binding.selector);
    sb.append('(');
    for (TypeBinding paramType : binding.parameters) {
      sb.append(paramType.signature());
    }
    sb.append(')');
    sb.append(binding.returnType.signature());
    return sb.toString();
  }

  public static String signature(TypeBinding binding) {
    assert !binding.isIntersectionType18() && !binding.isIntersectionType();
    if (binding.isBaseType()) {
      return String.valueOf(binding.sourceName());
    } else {
      return String.valueOf(binding.constantPoolName());
    }
  }

  public static void setClassDispositionFromBinding(SourceTypeBinding binding, JDeclaredType type) {
    if (binding.isNestedType()) {
      if (isLocalClass(binding)) {
        type.setClassDisposition(JDeclaredType.NestedClassDisposition.LOCAL);
      } else if (binding.isAnonymousType()) {
        type.setClassDisposition(JDeclaredType.NestedClassDisposition.ANONYMOUS);
      } else if (isInnerClass(binding)) {
        type.setClassDisposition(JDeclaredType.NestedClassDisposition.INNER);
      } else if (isStaticClass(binding)) {
        type.setClassDisposition(JDeclaredType.NestedClassDisposition.STATIC);
      }
    } else {
      type.setClassDisposition(JDeclaredType.NestedClassDisposition.TOP_LEVEL);
    }
  }

  public static boolean isLocalClass(SourceTypeBinding binding) {
    return binding.isLocalType() && !binding.isAnonymousType();
  }

  public static boolean isStaticClass(SourceTypeBinding binding) {
    return binding.isNestedType() && binding.isStatic();
  }

  /**
   * Returns {@code true} if {@code typeBinding} is {@code JavaScriptObject} or
   * any subtype.
   */
  public static boolean isJso(TypeBinding typeBinding) {
    if (!(typeBinding instanceof ReferenceBinding)) {
      return false;
    }
    ReferenceBinding binding = (ReferenceBinding) typeBinding;
    while (binding != null) {
      if (JSO_CLASS.equals(String.valueOf(binding.constantPoolName()))) {
        return true;
      }
      binding = binding.superclass();
    }
    return false;
  }

  /**
   * Returns {@code true} if {@code typeBinding} is a subtype of
   * {@code JavaScriptObject}, but not {@code JavaScriptObject} itself.
   */
  public static boolean isJsoSubclass(TypeBinding typeBinding) {
    if (!(typeBinding instanceof ReferenceBinding)) {
      return false;
    }
    ReferenceBinding binding = (ReferenceBinding) typeBinding;
    return isJso(binding.superclass());
  }

  public static Iterable<ReferenceBinding> getSuperInterfacesRequiringInitialization(
      ReferenceBinding type) {
    Iterable<ReferenceBinding> interfaces = Collections.emptyList();
    for (ReferenceBinding interfaceType : type.superInterfaces()) {
      interfaces =
          Iterables.concat(interfaces, getSuperInterfacesRequiringInitialization(interfaceType));
      if (hasDefaultMethods(interfaceType)) {
        interfaces = Iterables.concat(interfaces, Collections.singleton(interfaceType));
      }
    }
    return interfaces;
  }

  private static boolean hasDefaultMethods(ReferenceBinding interfaceType) {
    return Iterables.any(Arrays.asList(interfaceType.methods()), new Predicate<MethodBinding>() {
      @Override
      public boolean apply(MethodBinding methodBinding) {
        return methodBinding.isDefaultMethod();
      }
    });
  }

  /*
   * Implicit conversion helpers.
   */

  public static boolean requiresBoxing(int implicitConversion) {
    return implicitConversion != -1
        && (implicitConversion & TypeIds.BOXING) != 0;
  }

  public static boolean requiresUnboxing(int implicitConversion) {
    return implicitConversion != -1
        && (implicitConversion & TypeIds.UNBOXING) != 0;
  }

  public static BaseTypeBinding getBoxingPrimitiveType(ClassScope scope, int implicitConversion) {
    int typeId = (implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
    return getBaseTypeBinding(scope, typeId);
  }

  public static BaseTypeBinding getUnboxingPrimitiveType(
      ClassScope scope, int implicitConversion) {
    if (needsCastBeforeUnbox(scope, implicitConversion)) {
      int typeId = (implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
      return getBaseTypeBinding(scope, typeId);
    }
    int compileTypeId = implicitConversion & TypeIds.COMPILE_TYPE_MASK;
    return getBaseTypeBinding(scope, compileTypeId);
  }

  public static BaseTypeBinding getBaseTypeBinding(ClassScope scope, int typeId) {
    return  (BaseTypeBinding) TypeBinding.wellKnownType(scope, typeId);
  }

  public static ReferenceBinding getBoxedTypeBinding(
      ClassScope scope, BaseTypeBinding primitiveType) {
    return (ReferenceBinding) scope.boxing(primitiveType);
  }

  public static boolean needsCastBeforeUnbox(ClassScope scope, int implicitConversion) {
    // values of specific types like j.l.Object need casting before auto unboxing.
    int compileTypeId = implicitConversion & TypeIds.COMPILE_TYPE_MASK;
    return !(TypeBinding.wellKnownType(scope, compileTypeId) instanceof BaseTypeBinding);
  }

  private static final String VALUE_SUFFIX = "Value";
  private static final String VALUE_OF_METHOD_NAME = "valueOf";

  private static final char[] VALUE_SUFFIX_ = VALUE_SUFFIX.toCharArray();
  private static final char[] VALUE_OF_ = VALUE_OF_METHOD_NAME.toCharArray();

  public static MethodBinding getBoxingMethodBinding(
      ClassScope scope, BaseTypeBinding primitiveType) {
    ReferenceBinding boxType = (ReferenceBinding) scope.boxing(primitiveType);
    MethodBinding valueOfMethod = boxType.getExactMethod(VALUE_OF_,
        new TypeBinding[]{primitiveType}, scope.compilationUnitScope());
    assert valueOfMethod != null;
    return valueOfMethod;
  }

  public static MethodBinding getUnboxingMethodBinding(
      ClassScope scope, BaseTypeBinding primitiveType) {
    ReferenceBinding boxType = (ReferenceBinding) scope.boxing(primitiveType);
    char[] selector = CharOperation.concat(primitiveType.simpleName, VALUE_SUFFIX_);

    MethodBinding valueMethod =
        boxType.getExactMethod(selector, new TypeBinding[0], scope.compilationUnitScope());
    assert valueMethod != null;
    return valueMethod;
  }
}
