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

import static javaemul.internal.InternalPreconditions.checkType;

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

import javaemul.internal.annotations.HasNoSideEffects;

// CHECKSTYLE_NAMING_OFF: Uses legacy conventions of underscore prefixes.

/**
 * This is a magic class the compiler uses to perform any cast operations that require code.<br />
 *
 * The cast operations are only as accurate as the contents of the castableTypeMaps and should not
 * be used directly by user code. The compiler takes care to record most cast operations in user
 * code so that it can build limited but accurate castableTypeMaps.
 */
final class Cast {

  /**
   * As plain JavaScript Strings (not monkey patched) are used to model Java Strings,
   * {@code  stringCastMap} stores runtime type info for cast purposes for string objects.
   * Same applies to Double and Boolean.
   *
   * NOTE: it is important that the field is left uninitialized so that Cast does not
   * require a clinit.
   */
  // NOTE: if any of these three are edited, update JProgram.DispatchType's constructor
  private static JavaScriptObject stringCastMap;
  private static JavaScriptObject doubleCastMap;
  private static JavaScriptObject booleanCastMap;

  @HasNoSideEffects
  static native boolean canCast(Object src, JavaScriptObject dstId) /*-{
    if (@com.google.gwt.lang.Cast::instanceOfString(*)(src)) {
      return !!@com.google.gwt.lang.Cast::stringCastMap[dstId];
    } else if (src.@java.lang.Object::castableTypeMap) {
      return !!src.@java.lang.Object::castableTypeMap[dstId];
    } else if (@com.google.gwt.lang.Cast::instanceOfDouble(*)(src)) {
      return !!@com.google.gwt.lang.Cast::doubleCastMap[dstId];
    } else if (@com.google.gwt.lang.Cast::instanceOfBoolean(*)(src)) {
      return !!@com.google.gwt.lang.Cast::booleanCastMap[dstId];
    }
    return false;
  }-*/;

  @HasNoSideEffects
  static native boolean canCastClass(Class<?> srcClazz, Class<?> dstClass) /*-{
    var srcTypeId = srcClazz.@java.lang.Class::typeId;
    var dstTypeId = dstClass.@java.lang.Class::typeId;
    var prototype = @com.google.gwt.lang.Runtime::prototypesByTypeId[srcTypeId];
    return @com.google.gwt.lang.Cast::canCast(*)(prototype, dstTypeId);
  }-*/;

  static native String charToString(char x) /*-{
    return String.fromCharCode(x);
  }-*/;

  static Object castTo(Object src, JavaScriptObject dstId) {
    checkType(src == null || canCast(src, dstId));
    return src;
  }

  // NOTE: if any of these three are edited, update JProgram.DispatchType's constructor
  static Object castToString(Object src) {
    checkType(src == null || instanceOfString(src));
    return src;
  }

  static Object castToDouble(Object src) {
    checkType(src == null || instanceOfDouble(src));
    return src;
  }

  static Object castToBoolean(Object src) {
    checkType(src == null || instanceOfBoolean(src));
    return src;
  }

  /**
   * Allow a cast to an java.lang.Object array, accepting also untyped arrays.
   */
  static Object castToArray(Object src) {
    checkType(src == null || instanceOfArray(src));
    return src;
  }

  /**
   * Allow a cast to an array of Jsos, accepting also untyped arrays.
   */
  static Object castToJsoArray(Object src, JavaScriptObject dstId) {
    checkType(src == null || instanceOfJsoArray(src, dstId));
    return src;
  }

  /**
   * Allow a cast to (untyped) array. This case covers single and multidimensional JsType arrays.
   */
  static Object castToJsArray(Object src) {
    checkType(src == null || instanceOfJsArray(src));
    return src;
  }

  /**
   * Allow a dynamic cast to an object, always succeeding if it's a JSO.
   */
  static Object castToAllowJso(Object src, JavaScriptObject dstId) {
    checkType(src == null || isJavaScriptObject(src) || canCast(src, dstId));
    return src;
  }

  /**
   * Allow a cast to JSO only if there's no type ID.
   */
  static Object castToJso(Object src) {
    checkType(src == null || isJavaScriptObject(src));
    return src;
  }

  /**
   * Allow a dynamic cast to a JsFunction interface only if it is a function.
   */
  static Object castToFunction(Object src) {
    checkType(src == null || isFunction(src));
    return src;
  }

  /**
   * Allow a dynamic cast to a native GLOBAL.Object if it is JavaScript object.
   */
  static Object castToJsObject(Object src) {
    checkType(src == null || isJsObject(src));
    return src;
  }

  /**
   * A dynamic cast that optionally checks for JsType prototypes.
   */
  static Object castToNative(Object src, JavaScriptObject jsType) {
    checkType(src == null ||  jsinstanceOf(src, jsType));
    return src;
  }

  static Object castToUnknownNative(Object src) {
    return src;
  }

  static boolean instanceOf(Object src, JavaScriptObject dstId) {
    return (src != null) && canCast(src, dstId);
  }

  @HasNoSideEffects
  static native boolean instanceOfString(Object src) /*-{
    return typeof(src) === "string";
  }-*/;

  @HasNoSideEffects
  static native boolean instanceOfDouble(Object src) /*-{
    return typeof(src) === "number";
  }-*/;

  @HasNoSideEffects
  static native boolean instanceOfBoolean(Object src) /*-{
    return typeof(src) === "boolean";
  }-*/;

  /**
   * Returns true if {@code src} is Java object array or an untyped array.
   */
  static boolean instanceOfArray(Object src) {
    return isArray(src) && !Array.isPrimitiveArray(src);
  }

  /**
   * Returns true if {@code src} is Java object array or an untyped array.
   */
  static boolean instanceOfJsoArray(Object src, JavaScriptObject dstId) {
    return canCast(src, dstId) || !Util.hasTypeMarker(src) && isArray(src);
  }

  /**
   * Returns true if {@code src} is an array (native or not).
   */
  static boolean instanceOfJsArray(Object src) {
    return isArray(src);
  }

  static boolean instanceOfNative(Object src, JavaScriptObject jsType) {
    return jsinstanceOf(src, jsType);
  }

  static boolean instanceOfUnknownNative(Object src) {
    return src != null;
  }

  static boolean instanceOfJso(Object src) {
    return (src != null) && isJavaScriptObject(src);
  }

  /**
   * Returns true if the object is a Java object and can be cast, or if it's a
   * non-null JSO.
   */
  static boolean instanceOfAllowJso(Object src, JavaScriptObject dstId) {
    return (src != null) && (isJavaScriptObject(src) || canCast(src, dstId));
  }

  /**
   * Returns true if the object is a function.
   */
  static boolean instanceOfFunction(Object src) {
    return (src != null) && isFunction(src);
  }

  /**
   * Returns true if the object is a JS object.
   */
  static boolean instanceOfJsObject(Object src) {
    return (src != null) && isJsObject(src);
  }

  /**
   * Returns whether the Object is a function.
   */
  @HasNoSideEffects
  private static native boolean isFunction(Object src)/*-{
    return typeof(src) === "function";
  }-*/;

  @HasNoSideEffects
  private static native boolean isJsObject(Object src)/*-{
    return typeof(src) === "object" || typeof (src) == "function";
  }-*/;

  @HasNoSideEffects
  static boolean isJavaScriptObject(Object src) {
    // TODO(rluble): should return false to for plain arrays.
    return isJsObjectOrFunction(src) && !Util.hasTypeMarker(src);
  }

  @HasNoSideEffects
  private static native boolean isJsObjectOrFunction(Object src) /*-{
    return typeof(src) === "object" || typeof(src) === "function";
  }-*/;

  /**
   * Uses the not operator to perform a null-check; do NOT use on anything that
   * could be a String, 'unboxed' Double, or 'unboxed' Boolean.
   */
  static native boolean isNotNull(Object src) /*-{
    // Coerce to boolean.
    return !!src;
  }-*/;

  /**
   * Uses the not operator to perform a null-check; do NOT use on anything that
   * could be a String, 'unboxed' Double, or 'unboxed' Boolean.
   */
  static native boolean isNull(Object src) /*-{
    return !src;
  }-*/;

  static native boolean jsEquals(Object a, Object b) /*-{
    return a == b;
  }-*/;

  /**
   * Determine if object is an instanceof jsType regardless of window or frame.
   */
  @HasNoSideEffects
  private static native boolean jsinstanceOf(Object obj, JavaScriptObject jsType) /*-{
    return obj && jsType && obj instanceof jsType;
  }-*/;

  static native boolean jsNotEquals(Object a, Object b) /*-{
    return a != b;
  }-*/;

  static native Object maskUndefined(Object src) /*-{
    return (src == null) ? null : src;
  }-*/;

  /**
   * See JLS 5.1.3.
   */
  static native byte narrow_byte(double x) /*-{
    return x << 24 >> 24;
  }-*/;

  /**
   * See JLS 5.1.3.
   */
  static native char narrow_char(double x) /*-{
    return x & 0xFFFF;
  }-*/;

  /**
   * See JLS 5.1.3.
   */
  static native int narrow_int(double x) /*-{
    return x | 0;
  }-*/;

  /**
   * See JLS 5.1.3.
   */
  static native short narrow_short(double x) /*-{
    return x << 16 >> 16;
  }-*/;

  /**
   * See JLS 5.1.3 for why we do a two-step cast. First we round to int, then
   * narrow to byte.
   */
  static byte round_byte(double x) {
    return narrow_byte(round_int(x));
  }

  /**
   * See JLS 5.1.3 for why we do a two-step cast. First we round to int, then
   * narrow to char.
   */
  static char round_char(double x) {
    return narrow_char(round_int(x));
  }

  /**
   * See JLS 5.1.3.
   */
  static native int round_int(double x) /*-{
    // TODO: reference java.lang.Integer::MAX_VALUE when we get clinits fixed
    return Math.max(Math.min(x, 2147483647), -2147483648) | 0;
  }-*/;

  /**
   * See JLS 5.1.3 for why we do a two-step cast. First we rount to int, then
   * narrow to short.
   */
  static short round_short(double x) {
    return narrow_short(round_int(x));
  }

  /**
   * Check a statically false cast, which can succeed if the argument is null.
   * Called by compiler-generated code based on static type information.
   */
  static Object throwClassCastExceptionUnlessNull(Object o) throws ClassCastException {
    checkType(o == null);
    return o;
  }

  /**
   * Returns true if Object can dispatch instance methods and does not need a compiler
   * provided trampoline.
   *
   * Java non primitive objects fall into 3 classes: Strings, arrays (of primitive or non primitive
   * types) and regular Java Objects (all others).
   *
   * Only regular Java object have dynamic instance dispatch, strings and arrays need compiler
   * generated trampolines to implement instance dispatch.
   */
  static boolean hasJavaObjectVirtualDispatch(Object src) {
    return !isArray(src) && Util.hasTypeMarker(src);
  }

  @HasNoSideEffects
  /**
   * Returns true if {@code src} is a Java array.
   */
  static native boolean isArray(Object src) /*-{
    return Array.isArray(src);
  }-*/;

  @HasNoSideEffects
  static native Class<?> getClass(Object array) /*-{
    return array.@java.lang.Object::___clazz
        || Array.isArray(array) && @JavaScriptObject[]::class
        || @JavaScriptObject::class;
  }-*/;
}

// CHECKSTYLE_NAMING_ON
