/*
 * Copyright 2006 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 java.lang;

import com.google.gwt.core.client.JavaScriptObject;

import java.lang.reflect.Type;

import javaemul.internal.annotations.DoNotInline;

/**
 * Generally unsupported. This class is provided so that the GWT compiler can
 * choke down class literal references.
 * <p>
 * NOTE: The code in this class is very sensitive and should keep its dependencies upon other
 * classes to a minimum.
 *
 * @param <T> the type of the object
 */
public final class Class<T> implements Type {

  private static final int PRIMITIVE = 0x00000001;
  private static final int INTERFACE = 0x00000002;
  private static final int ARRAY = 0x00000004;
  private static final int ENUM = 0x00000008;

  /**
   * Create a Class object for an array.<p>
   *
   * Arrays are not registered in the prototype table and get the class literal explicitly at
   * construction.<p>
   *
   * NOTE: this method is accessed through JSNI (Violator pattern) to avoid changing the public API.
   */
  private static native <T> Class<T> getClassLiteralForArray(Class<?> leafClass,
      int dimensions) /*-{
    var arrayLiterals = leafClass.@Class::arrayLiterals = leafClass.@Class::arrayLiterals || [];
    return arrayLiterals[dimensions] || (arrayLiterals[dimensions] =
            leafClass.@Class::createClassLiteralForArray(I)(dimensions));
  }-*/;

  private <T> Class<T> createClassLiteralForArray(int dimensions) {
    Class<T> clazz = new Class<T>();
    clazz.modifiers = ARRAY;
    clazz.superclass = Object.class;
    if (dimensions > 1) {
      clazz.componentType = getClassLiteralForArray(this, dimensions - 1);
    } else {
      clazz.componentType = this;
    }
    return clazz;
  }

  /**
   * Create a Class object for a class.
   *
   * @skip
   */
  @DoNotInline
  static <T> Class<T> createForClass(String packageName, String compoundClassName,
      JavaScriptObject typeId, Class<? super T> superclass) {
    Class<T> clazz = createClassObject(packageName, compoundClassName, typeId);
    maybeSetClassLiteral(typeId, clazz);
    clazz.superclass = superclass;
    return clazz;
  }

  /**
   * Create a Class object for an enum.
   *
   * @skip
   */
  @DoNotInline
  static <T> Class<T> createForEnum(String packageName, String compoundClassName,
      JavaScriptObject typeId, Class<? super T> superclass,
      JavaScriptObject enumConstantsFunc, JavaScriptObject enumValueOfFunc) {
    Class<T> clazz = createClassObject(packageName, compoundClassName, typeId);
    maybeSetClassLiteral(typeId, clazz);
    clazz.modifiers = (enumConstantsFunc != null) ? ENUM : 0;
    clazz.superclass = clazz.enumSuperclass = superclass;
    clazz.enumConstantsFunc = enumConstantsFunc;
    clazz.enumValueOfFunc = enumValueOfFunc;
    return clazz;
  }

  /**
   * Create a Class object for an interface.
   *
   * @skip
   */
  @DoNotInline
  static <T> Class<T> createForInterface(String packageName, String compoundClassName) {
    Class<T> clazz = createClassObject(packageName, compoundClassName, null);
    clazz.modifiers = INTERFACE;
    return clazz;
  }

  /**
   * Create a Class object for a primitive.
   *
   * @skip
   */
  @DoNotInline
  static Class<?> createForPrimitive(String className, JavaScriptObject primitiveTypeId) {
    Class<?> clazz = createClassObject("", className, primitiveTypeId);
    clazz.typeId = primitiveTypeId;
    clazz.modifiers = PRIMITIVE;
    return clazz;
  }

  /**
    * Used by {@link WebModePayloadSink} to create uninitialized instances.
    */
   @DoNotInline
   static native JavaScriptObject getPrototypeForClass(Class<?> clazz) /*-{
     if (clazz.@Class::isPrimitive()()) {
       return null;
     }
     var typeId = clazz.@Class::typeId;
     var prototype = @com.google.gwt.lang.Runtime::prototypesByTypeId[typeId];
     return prototype;
   }-*/;

  public static boolean isClassMetadataEnabled() {
    // This body may be replaced by the compiler
    return true;
  }

  /**
   * null implies non-instantiable type, with no entries in
   * {@link Runtime::prototypesByTypeId}.
   */
  private static native boolean isInstantiable(JavaScriptObject typeId) /*-{
    return !!typeId;
  }-*/;

  /**
   * Creates the class object for a type and initiliazes its fields.
   */
  private static <T> Class<T> createClassObject(String packageName, String compoundClassName,
      JavaScriptObject typeId) {
    Class<T> clazz = new Class<T>();
    if (isClassMetadataEnabled()) {
      clazz.packageName = packageName;
      clazz.compoundName = compoundClassName;
    } else {
      synthesizeClassNamesFromTypeId(clazz, typeId);
    }
    return clazz;
  }

  /**
   * Install class literal into prototype.clazz field (if type is instantiable) such that
   * Object.getClass() returning this.clazz returns the literal. Also stores typeId on class literal
   * for looking up prototypes given a literal. This is used for deRPC at the moment, but may be
   * used to implement Class.newInstance() in the future.
   *
   * If the prototype for typeId has not yet been created, then install the literal into a
   * placeholder array to differentiate the two cases.
   */
  private static native void maybeSetClassLiteral(JavaScriptObject typeId, Class<?> clazz) /*-{
    var proto;
    if (!typeId) {
      // Type is not instantiable, hence not registered in the metadata table.
      return;
    }
    clazz.@Class::typeId = typeId;
    // Guarantees virtual method won't be pruned by using a JSNI ref
    // This is required because deRPC needs to call it.
    var prototype  = @Class::getPrototypeForClass(Ljava/lang/Class;)(clazz);
    // A class literal may be referenced prior to an async-loaded vtable setup
    // For example, class literal lives in inital fragment,
    // but type is instantiated in another fragment
    if (!prototype) {
      // Leave a place holder for now to be filled in by __defineClass__ later.
      // TODO(rluble): Do not rely on the fact that if the entry is an array it is a placeholder.
      @com.google.gwt.lang.Runtime::prototypesByTypeId[typeId] = [clazz];
      return;
    }
    // Type already registered in the metadata table, install the class literal in the appropriate
    // prototype field.
    prototype.@java.lang.Object::___clazz = clazz;
  }-*/;

  /**
   * Initiliazes {@code clazz} names from metadata.
   * <p>
   * Written in JSNI to minimize dependencies (on String.+).
   */
  private static native void initializeNames(Class<?> clazz) /*-{
    if (clazz.@Class::isArray(*)()) {
      var componentType = clazz.@Class::componentType;
      if (componentType.@Class::isPrimitive()()) {
        clazz.@Class::typeName = "[" + componentType.@Class::typeId;
      } else  if (!componentType.@Class::isArray()()) {
        clazz.@Class::typeName = "[L" + componentType.@Class::getName()() + ";";
      } else {
        clazz.@Class::typeName = "[" + componentType.@Class::getName()();
      }
      clazz.@Class::canonicalName = componentType.@Class::getCanonicalName()() + "[]";
      clazz.@Class::simpleName = componentType.@Class::getSimpleName()() + "[]";
      return;
    }

    var packageName = clazz.@Class::packageName;
    var compoundName = clazz.@Class::compoundName;
    compoundName =  compoundName.split("/");
    clazz.@Class::typeName =
        @Class::join(*)('.', [packageName , @Class::join(*)("$", compoundName)]);
    clazz.@Class::canonicalName =
        @Class::join(*)('.', [packageName , @Class::join(*)(".", compoundName)]);
    clazz.@Class::simpleName = compoundName[compoundName.length - 1];
  }-*/;

  /**
   * Joins an array of strings with the specified separator.
   * <p>
   * Written in JSNI to minimize dependencies (on String.+).
   */
  private static native String join(String separator, JavaScriptObject strings) /*-{
    var i = 0;
    while (!strings[i] || strings[i] == "") {
      i++;
    }
    var result = strings[i++];
    for (; i < strings.length; i++) {
      if  (!strings[i] || strings[i] == "") {
        continue;
      }
      result += separator + strings[i];
    }
    return result;
  }-*/;

  /**
   * Initiliazes {@code clazz} names from typeIds.
   * <p>
   * Only called if metadata IS disabled.
   * <p>
   * Written in JSNI to minimize dependencies (on toString() and String.+).
   */
  static native void synthesizeClassNamesFromTypeId(Class<?> clazz, JavaScriptObject typeId) /*-{
     // The initial "" + in the below code is to prevent clazz.getAnonymousId from
     // being autoboxed. The class literal creation code is run very early
     // during application start up, before class Integer has been initialized.

    clazz.@Class::typeName = "Class$" +
        (!!typeId ? "S" + typeId : "" + clazz.@Class::sequentialId);
    clazz.@Class::canonicalName = clazz.@Class::typeName;
    clazz.@Class::simpleName = clazz.@Class::typeName;
  }-*/;

  /**
   * Sets the class object for primitives.
   * <p>
   * Written in JSNI to minimize dependencies (on (String)+).
   */
  static native void synthesizePrimitiveNamesFromTypeId(Class<?> clazz,
      JavaScriptObject primitiveTypeId) /*-{
    clazz.@Class::typeName = "Class$" + primitiveTypeId;
    clazz.@Class::canonicalName = clazz.@Class::typeName;
    clazz.@Class::simpleName = clazz.@Class::typeName;
  }-*/;

  JavaScriptObject enumValueOfFunc;

  int modifiers;

  private Class<?> componentType;

  @SuppressWarnings("unused")
  private JavaScriptObject enumConstantsFunc;

  private Class<? super T> enumSuperclass;

  private Class<? super T> superclass;

  private String simpleName;

  private String typeName;

  private String canonicalName;

  private String packageName;

  private String compoundName;

  private JavaScriptObject typeId;

  private JavaScriptObject arrayLiterals;

  // Assign a sequential id to each class literal to avoid calling hashCode which bring Impl as
  // a dependency.
  private int sequentialId = nextSequentialId++;

  private static int nextSequentialId = 1;

  /**
   * Not publicly instantiable.
   *
   * @skip
   */
  private Class() {
    // Initialize in constructor to avoid V8 invalidating hidden classes.
    typeName = null;
    simpleName = null;
    packageName = null;
    compoundName = null;
    canonicalName = null;
    typeId = null;
    arrayLiterals = null;
  }

  public boolean desiredAssertionStatus() {
    // This body is ignored by the JJS compiler and a new one is
    // synthesized at compile-time based on the actual compilation arguments.
    return false;
  }

  private void ensureNamesAreInitialized() {
    if (typeName != null) {
      return;
    }
    initializeNames(this);
  }

  public String getCanonicalName() {
    ensureNamesAreInitialized();
    return canonicalName;
  }

  public Class<?> getComponentType() {
    return componentType;
  }

  public native T[] getEnumConstants() /*-{
    return this.@Class::enumConstantsFunc
        && (this.@Class::enumConstantsFunc)();
  }-*/;

  public String getName() {
    ensureNamesAreInitialized();
    return typeName;
  }

  public String getSimpleName() {
    ensureNamesAreInitialized();
    return simpleName;
  }

  public Class<? super T> getSuperclass() {
    if (isClassMetadataEnabled()) {
      return superclass;
    } else {
      return null;
    }
  }

  public boolean isArray() {
    return (modifiers & ARRAY) != 0;
  }

  public boolean isEnum() {
    return (modifiers & ENUM) != 0;
  }

  public boolean isInterface() {
    return (modifiers & INTERFACE) != 0;
  }

  public boolean isPrimitive() {
    return (modifiers & PRIMITIVE) != 0;
  }

  @Override
  public String toString() {
    return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
        + getName();
  }

  /**
   * Used by Enum to allow getSuperclass() to be pruned.
   */
  Class<? super T> getEnumSuperclass() {
    return enumSuperclass;
  }
}
