/*
 * Copyright 2007 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.
 */

/*
 * Defines the JavaScript classes gwt_nativewrapper_class and
 * gwt_functionwrapper_class, which interface via JNI to Java objects.
 */

#include <jni.h>
#include "JsRootedValue.h"
#include "gwt-jni.h"
#include "Tracer.h"

/*
 * Helper function to get reference Java attributes from Javascript.
 * 
 * cx - JSContext pointer
 * obj - JavaScript object which is a wrapped Java object
 * id - property name, as a jsval string
 * dispClass - output parameter of DispatchMethod subclass
 * dispObj - output parameter of Java object
 * jident - output parameter of property name as a Java string
 */
static JSBool getJavaPropertyStats(JSContext *cx, JSObject *obj, jsval id,
    jclass& dispClass, jobject& dispObj, jstring& jident)
{
  Tracer tracer("getJavaPropertyStats");
  if (!JSVAL_IS_STRING(id)) {
    tracer.setFail("id is not a string");
    return JS_FALSE;
  }

  jident = savedJNIEnv->NewString(JS_GetStringChars(JSVAL_TO_STRING(id)),
      JS_GetStringLength(JSVAL_TO_STRING(id)));
  if (!jident || savedJNIEnv->ExceptionCheck()) {
    tracer.setFail("unable to create Java string");
    return JS_FALSE;
  }

  dispObj = NS_REINTERPRET_CAST(jobject, JS_GetPrivate(cx, obj));
  if (!dispObj) {
    tracer.setFail("can't get dispatch object");
    return JS_FALSE;
  }

  dispClass = savedJNIEnv->GetObjectClass(dispObj);
  if (savedJNIEnv->ExceptionCheck()) {
    tracer.setFail("can't get class of dispatch object");
    return JS_FALSE;
  }

  return JS_TRUE;
}
  
/*
 * Returns the value of a field on a Java object.
 * 
 * context - JavaScript context
 * clazz - class of obj
 * obj - Java object to retreive field from
 * fieldName - name of field on Java object to retrieve
 * 
 * Returns null on failure.  Caller is responsible for deleting
 * returned JsRootedValue when done with it.
 */
static JsRootedValue* GetFieldAsRootedValue(JSContext* cx, jclass clazz,
    jobject obj, jstring fieldName)
{
  Tracer tracer("GetFieldAsRootedValue");
  JsRootedValue::ContextManager context(cx);
  jmethodID getFieldMeth = savedJNIEnv->GetMethodID(clazz, "getField",
      "(Ljava/lang/String;I)V");
  if (!getFieldMeth || savedJNIEnv->ExceptionCheck()) {
    return 0;
  }

  JsRootedValue* jsRootedValue = new JsRootedValue();
  savedJNIEnv->CallVoidMethod(obj, getFieldMeth, fieldName,
    reinterpret_cast<jint>(jsRootedValue));
  if (savedJNIEnv->ExceptionCheck()) {
    delete jsRootedValue;
    return 0;
  }
  return jsRootedValue;
}
  
/*
 * Sets the value of a field on a Java object.
 * 
 * context - JavaScript context
 * clazz - class of obj
 * obj - Java object to store into field
 * fieldName - name of field on Java object to store into
 * jsRootedValue - the value to store in the field
 * 
 * returns true on success, false on failure
 */
static bool SetFieldFromRootedValue(JSContext* cx, jclass clazz,
    jobject obj, jstring fieldName, JsRootedValue* jsRootedValue)
{
  Tracer tracer("SetFieldAsRootedValue");
  JsRootedValue::ContextManager context(cx);
  jmethodID getFieldMeth = savedJNIEnv->GetMethodID(clazz, "setField",
      "(Ljava/lang/String;I)V");
  if (!getFieldMeth || savedJNIEnv->ExceptionCheck()) {
    return false;
  }

  savedJNIEnv->CallVoidMethod(obj, getFieldMeth, fieldName,
    reinterpret_cast<jint>(jsRootedValue));
  if (savedJNIEnv->ExceptionCheck()) {
    return false;
  }

  return true;
}

static JSBool JS_DLL_CALLBACK gwt_nativewrapper_getProperty(JSContext *cx,
    JSObject *obj, jsval id, jsval *vp)
{
  Tracer tracer("gwt_nativewrapper_getProperty");
  tracer.log("context=%08x", unsigned(cx));
  if (*vp != JSVAL_VOID) {
    return JS_TRUE;
  }
  JsRootedValue::ContextManager context(cx);

  jclass dispClass;
  jobject dispObj;
  jstring ident;
  if (!getJavaPropertyStats(cx, obj, id, dispClass, dispObj, ident)) {
    tracer.setFail("getJavaPropertyStats failed");
    return JS_FALSE;
  }
  JsRootedValue* js_rooted_value = GetFieldAsRootedValue(cx, dispClass,
      dispObj, ident);
  if (!js_rooted_value) {
    tracer.setFail("can't get field");
    return JS_FALSE;
  }
  *vp = js_rooted_value->getValue();
  return JS_TRUE;
}

static void JS_DLL_CALLBACK gwt_nativewrapper_finalize(JSContext *cx,
    JSObject *obj)
{
  Tracer tracer("gwt_nativewrapper_finalize");
  jobject dispObj = NS_REINTERPRET_CAST(jobject, JS_GetPrivate(cx, obj));
  if (dispObj) {
    // Remove this pairing from the global map.
    jmethodID removeMethod = savedJNIEnv->GetStaticMethodID(lowLevelMozClass, "removeJsvalForObject",
      "(Ljava/lang/Object;)V");
    if (!removeMethod || savedJNIEnv->ExceptionCheck()) {
      tracer.setFail("Cannot GetMethodID for removeJsvalForObject");
      return;
    }
    savedJNIEnv->CallStaticVoidMethod(lowLevelMozClass, removeMethod, dispObj);
    if (savedJNIEnv->ExceptionCheck()) {
      tracer.setFail("Exception calling removeJsvalForObject");
      return;
    }
    savedJNIEnv->DeleteGlobalRef(dispObj);
  }
}

static JSBool JS_DLL_CALLBACK gwt_nativewrapper_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
  Tracer tracer("gwt_nativewrapper_setProperty");
  tracer.log("context=%08x", unsigned(cx));
  JsRootedValue::ContextManager context(cx);
  jclass dispClass;
  jobject dispObj;
  jstring ident;
  if (!getJavaPropertyStats(cx, obj, id, dispClass, dispObj, ident)) {
    tracer.setFail("getJavaPropertyStats failed");
    return JS_FALSE;
  }
  JsRootedValue* js_rooted_value = new JsRootedValue(*vp); 
  if (!SetFieldFromRootedValue(cx, dispClass, dispObj, ident,
      js_rooted_value)) {
    tracer.setFail("can't set field");
    return JS_FALSE;
  }
  return JS_TRUE;
}

JSClass gwt_nativewrapper_class = {
  "gwt_nativewrapper_class", JSCLASS_HAS_PRIVATE,
  JS_PropertyStub, JS_PropertyStub, gwt_nativewrapper_getProperty,
  gwt_nativewrapper_setProperty, JS_EnumerateStub, JS_ResolveStub,
  JS_ConvertStub, gwt_nativewrapper_finalize,
  JSCLASS_NO_OPTIONAL_MEMBERS
};

JSClass gwt_functionwrapper_class = {
  "gwt_functionwrapper_class", JSCLASS_HAS_PRIVATE,
  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, gwt_nativewrapper_finalize,
  JSCLASS_NO_OPTIONAL_MEMBERS
};
