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

#include "JavaObject.h"
#include "FFSessionHandler.h"
#include "SessionData.h"
#include "ServerMethods.h"
#include "Debug.h"
#include "XpcomDebug.h"
#include "HostChannel.h"
#include "InvokeMessage.h"
#include "ReturnMessage.h"
#include "scoped_ptr/scoped_ptr.h"

static JSClass JavaObjectClass = {
  "GWTJavaObject", /* class name */
  JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_NEW_ENUMERATE, /* flags */

  JS_PropertyStub, /* add property */
  JS_PropertyStub, /* delete property */
  JavaObject::getProperty, /* get property */
  JavaObject::setProperty, /* set property */

  reinterpret_cast<JSEnumerateOp>(JavaObject::enumerate), /* enumerate */
  JS_ResolveStub, /* resolve */
  JS_ConvertStub, // JavaObject::convert, /* convert */
  JavaObject::finalize, /* finalize */ //TODO

  NULL, /* object hooks */
  NULL, /* check access */
#if GECKO_VERSION < 2000
  JavaObject::call, /* call */ //TODO
#else
  JavaObject::call20, /* call: compatability wrapper for 2.0+ */
#endif //GECKO_VERSION
  NULL, /* construct */
  NULL, /* object serialization */
  NULL, /* has instance */
  NULL, /* mark */
  NULL /* reserve slots */
};

int JavaObject::getObjectId(JSContext* ctx, JSObject* obj) {
  jsval val;
  JSClass* jsClass = JS_GET_CLASS(ctx, obj);
  if (jsClass != &JavaObjectClass) {
    Debug::log(Debug::Error)
        << "JavaObject::getObjectId called on non-JavaObject: " << jsClass->name
        << Debug::flush;
    return -1;
  }
  if (JSCLASS_RESERVED_SLOTS(jsClass) < 1) {
    Debug::log(Debug::Error)
        << "JavaObject::getObjectId -- " << static_cast<void*>(obj)
        << " has only " << (JSCLASS_RESERVED_SLOTS(jsClass))
        << " reserved slots, no objectId present" << Debug::flush;
    return -1;
  }
  if (!JS_GetReservedSlot(ctx, obj, 0, &val)) {
    Debug::log(Debug::Error) << "Error getting reserved slot" << Debug::flush;
    return -1;
  }
  // TODO: assert JSVAL_IS_INT(val)
  return JSVAL_TO_INT(val);
}

SessionData* JavaObject::getSessionData(JSContext* ctx, JSObject* obj) {
  void* data = JS_GetInstancePrivate(ctx, obj, &JavaObjectClass, NULL);
  return static_cast<SessionData*>(data);
}


bool JavaObject::isJavaObject(JSContext* ctx, JSObject* obj) {
  return JS_GET_CLASS(ctx, obj) == &JavaObjectClass;
}

JSObject* JavaObject::construct(JSContext* ctx, SessionData* data, int objectRef) {
  // TODO: prototype? parent?
  Debug::log(Debug::Spam) << "JavaObject::construct objectId=" << objectRef << Debug::flush;
  JSObject* obj = JS_NewObject(ctx, &JavaObjectClass, NULL, NULL);
  Debug::log(Debug::Spam) << "  obj=" << obj << Debug::flush;
  if (!obj) {
    return NULL;
  }
  // set the session data
  if (!JS_SetPrivate(ctx, obj, data)) {
    Debug::log(Debug::Error) << "Could not set private data" << Debug::flush;
    return NULL;
  }
  // set the objectId
  if (!JS_SetReservedSlot(ctx, obj, 0, INT_TO_JSVAL(objectRef))) {
    Debug::log(Debug::Error) << "Could not set reserved slot" << Debug::flush;
    return NULL;
  }
  // define toString (TODO: some way to avoid doing this each time)
#if GECKO_VERSION < 2000
  if (!JS_DefineFunction(ctx, obj, "toString", JavaObject::toString, 0, 0)) {
    Debug::log(Debug::Error) << "Could not define toString method on object"
        << Debug::flush;
  }
#else
  if (!JS_DefineFunction(ctx, obj, "toString", JavaObject::toString20, 0, 0)) {
    Debug::log(Debug::Error) << "Could not define toString method on object"
        << Debug::flush;
  }
#endif //GECKO_VERSION
  return obj;
}

JSBool JavaObject::getProperty(JSContext* ctx, JSObject* obj, jsid id,
    jsval* rval) {
  Debug::log(Debug::Spam) << "JavaObject::getProperty obj=" << obj << Debug::flush;
  SessionData* data = JavaObject::getSessionData(ctx, obj);
  if (!data) {
    // TODO: replace the frame with an error page instead?
    *rval = JSVAL_VOID;
    return JS_TRUE;
  }
  int objectRef = JavaObject::getObjectId(ctx, obj);
  if (JSID_IS_STRING(id)) {
    JSString* str = JSID_TO_STRING(id);
    if ((JS_GetStringEncodingLength(ctx, str) == 8) && !strncmp("toString",
          JS_EncodeString(ctx, str), 8)) {
      *rval = data->getToStringTearOff();
      return JS_TRUE;
    }
    if ((JS_GetStringEncodingLength(ctx, str) == 2) && !strncmp("id",
          JS_EncodeString(ctx, str), 2)) {
      *rval = INT_TO_JSVAL(objectRef);
      return JS_TRUE;
    }
    if ((JS_GetStringEncodingLength(ctx, str) == 16) && !strncmp("__noSuchMethod__",
          JS_EncodeString(ctx, str), 16)) {
      // Avoid error spew if we are disconnected
      *rval = JSVAL_VOID;
      return JS_TRUE;
    }
    Debug::log(Debug::Error) << "Getting unexpected string property "
        << dumpJsVal(ctx, id) << Debug::flush;
    // TODO: throw a better exception here
    return JS_FALSE;
  }
  if (!JSID_IS_INT(id)) {
    Debug::log(Debug::Error) << "Getting non-int/non-string property "
          << dumpJsVal(ctx, id) << Debug::flush;
    // TODO: throw a better exception here
    return JS_FALSE;
  }
  int dispId = JSID_TO_INT(id);

  HostChannel* channel = data->getHostChannel();
  SessionHandler* handler = data->getSessionHandler();

  Value value = ServerMethods::getProperty(*channel, handler, objectRef, dispId);
  data->makeJsvalFromValue(*rval, ctx, value);
  return JS_TRUE;
}

#if GECKO_VERSION < 2000
JSBool JavaObject::setProperty(JSContext* ctx, JSObject* obj, jsid id,
    jsval* vp) {
#else
JSBool JavaObject::setProperty(JSContext* ctx, JSObject* obj, jsid id,
    JSBool strict, jsval* vp) {
#endif //GECKO_VERSION

  Debug::log(Debug::Spam) << "JavaObject::setProperty obj=" << obj << Debug::flush;
  if (!JSID_IS_INT(id)) {
    Debug::log(Debug::Error) << "  Error: setting string property id" << Debug::flush;
    // TODO: throw a better exception here
    return JS_FALSE;
  }

  SessionData* data = JavaObject::getSessionData(ctx, obj);
  if (!data) {
    return JS_TRUE;
  }

  int objectRef = JavaObject::getObjectId(ctx, obj);
  int dispId = JSID_TO_INT(id);

  Value value;
  data->makeValueFromJsval(value, ctx, *vp);

  HostChannel* channel = data->getHostChannel();
  SessionHandler* handler = data->getSessionHandler();

  if (!ServerMethods::setProperty(*channel, handler, objectRef, dispId, value)) {
    // TODO: throw a better exception here
    return JS_FALSE;
  }
  return JS_TRUE;
}

// TODO: can this be removed now?
JSBool JavaObject::convert(JSContext* ctx, JSObject* obj, JSType type, jsval* vp) {
  Debug::log(Debug::Spam) << "JavaObject::convert obj=" << obj
      << " type=" << type << Debug::flush;
  switch (type) {
    case JSTYPE_STRING:
      return toString(ctx, obj, 0, NULL, vp);
    case JSTYPE_VOID:
      *vp = JSVAL_VOID;
      return JS_TRUE;
    case JSTYPE_NULL:
      *vp = JSVAL_NULL;
      return JS_TRUE;
    case JSTYPE_OBJECT:
      *vp = OBJECT_TO_JSVAL(obj);
      return JS_TRUE;
    default:
      break;
  }
  return JS_FALSE;
}

/**
 * List of property names we want to fake on wrapped Java objects.
 */
static const char* propertyNames[] = {
    "toString",
    "id",
};
#define NUM_PROPERTY_NAMES (sizeof(propertyNames) / sizeof(propertyNames[0]))

JSBool JavaObject::enumerate(JSContext* ctx, JSObject* obj, JSIterateOp op,
    jsval* statep, jsid* idp) {
  int objectId = JavaObject::getObjectId(ctx, obj);
  switch (op) {
    case JSENUMERATE_INIT:
      Debug::log(Debug::Spam) << "JavaObject::enumerate(oid=" << objectId
          << ", INIT)" << Debug::flush;
      *statep = JSVAL_ZERO;
      if (idp) {
        *idp = INT_TO_JSID(NUM_PROPERTY_NAMES);
      }
      break;
    case JSENUMERATE_NEXT:
    {
      int idNum = JSVAL_TO_INT(*statep);
      Debug::log(Debug::Spam) << "JavaObject::enumerate(oid=" << objectId
          << ", NEXT " << idNum << ")" << Debug::flush;
      *statep = INT_TO_JSVAL(idNum + 1);
      if (idNum >= NUM_PROPERTY_NAMES) {
        *statep = JSVAL_NULL;
#if GECKO_VERSION < 2000
	//TODO(jat): do we need to do this?
        *idp = JSVAL_NULL;
#endif //GECKO_VERSION
      } else {
        const char* propName = propertyNames[idNum];
        JSString* str = JS_NewStringCopyZ(ctx, propName);
        return JS_ValueToId(ctx, STRING_TO_JSVAL(str), idp);
      }
      break;
    }
    case JSENUMERATE_DESTROY:
      Debug::log(Debug::Spam) << "JavaObject::enumerate(oid=" << objectId
          << ", DESTROY)" << Debug::flush;
      *statep = JSVAL_NULL;
      break;
    default:
      Debug::log(Debug::Error) << "Unknown Enumerate op " <<
          static_cast<int>(op) << Debug::flush;
      return JS_FALSE;
  }
  return JS_TRUE;
}

void JavaObject::finalize(JSContext* ctx, JSObject* obj) {
  Debug::log(Debug::Spam) << "JavaObject::finalize obj=" << obj
      << " objId=" << JavaObject::getObjectId(ctx, obj) << Debug::flush;
  SessionData* data = JavaObject::getSessionData(ctx, obj);
  if (data) {
    int objectId = JavaObject::getObjectId(ctx, obj);
    data->freeJavaObject(objectId);
    JS_SetPrivate(ctx, obj, NULL);
  }
}

JSBool JavaObject::toString(JSContext* ctx, JSObject* obj, uintN argc,
    jsval* argv, jsval* rval) {
  SessionData* data = JavaObject::getSessionData(ctx, obj);
  if (!data) {
    *rval = JSVAL_VOID;
    return JS_TRUE;
  }
  int oid = getObjectId(ctx, obj);
  Debug::log(Debug::Spam) << "JavaObject::toString(id=" << oid << ")"
      << Debug::flush;
  Value javaThis;
  javaThis.setJavaObject(oid);
  // we ignore any supplied parameters
  return invokeJava(ctx, data, javaThis, InvokeMessage::TOSTRING_DISP_ID, 0,
      NULL, rval);
}

/**
 * Called when the JavaObject is invoked as a function.
 * We ignore the JSObject* argument, which is the 'this' context, which is
 * usually the window object. The JavaObject instance is in argv[-2].
 *
 * Returns a JS array, with the first element being a boolean indicating that
 * an exception occured, and the second element is either the return value or
 * the exception which was thrown.  In this case, we always return false and
 * raise the exception ourselves.
 */
JSBool JavaObject::call(JSContext* ctx, JSObject*, uintN argc, jsval* argv,
    jsval* rval) {
  // Get the JavaObject called as a function
  JSObject* obj = JSVAL_TO_OBJECT(argv[-2]);
  if (argc < 2 || !JSVAL_IS_INT(argv[0]) || !JSVAL_IS_OBJECT(argv[1])) {
    Debug::log(Debug::Error) << "JavaObject::call incorrect arguments" << Debug::flush;
    return JS_FALSE;
  }
  int dispId = JSVAL_TO_INT(argv[0]);
  if (Debug::level(Debug::Spam)) {
    Debug::DebugStream& dbg = Debug::log(Debug::Spam) << "JavaObject::call oid="
        << JavaObject::getObjectId(ctx, obj) << ",dispId=" << dispId << " (";
    for (unsigned i = 2; i < argc; ++i) {
      if (i > 2) {
        dbg << ", ";
      }
      dbg << dumpJsVal(ctx, argv[i]);
    }
    dbg << ")" << Debug::flush;
  }

  SessionData* data = JavaObject::getSessionData(ctx, obj);
  if (!data) {
    *rval = JSVAL_VOID;
    return JS_TRUE;
  }
  Debug::log(Debug::Spam) << "Data = " << data << Debug::flush;

  Value javaThis;
  if (!JSVAL_IS_NULL(argv[1])) {
    JSObject* thisObj = JSVAL_TO_OBJECT(argv[1]);
    if (isJavaObject(ctx, thisObj)) {
      javaThis.setJavaObject(getObjectId(ctx, thisObj));
    } else {
      data->makeValueFromJsval(javaThis, ctx, argv[1]);
    }
  } else {
    int oid = getObjectId(ctx, obj);
    javaThis.setJavaObject(oid);
  }
  return invokeJava(ctx, data, javaThis, dispId, argc - 2, &argv[2], rval);
}

#if GECKO_VERSION >= 2000
/**
 * Compatability wrapper for Gecko 2.0+
 */
JSBool JavaObject::toString20(JSContext* ctx, uintN argc, jsval* vp) {
  jsval rval = JSVAL_VOID;
  JSBool success;
  success = toString(ctx, JS_THIS_OBJECT(ctx, vp), argc, JS_ARGV(ctx, vp),
                       &rval);
  JS_SET_RVAL(cx, vp, rval);
  return success;
}

/**
 * Compatability wrapper method for Gecko 2.0+
 */
JSBool JavaObject::call20(JSContext* ctx, uintN argc, jsval* vp) {
  jsval rval = JSVAL_VOID;
  JSBool success;
  success = call(ctx, NULL, argc, JS_ARGV(ctx, vp), &rval);
  JS_SET_RVAL(ctx, vp, rval);
  return success;
}
#endif //GECKO_VERSION

/**
 * Calls a method on a Java object and returns a two-element JS array, with
 * the first element being a boolean flag indicating an exception was thrown,
 * and the second element is the actual return value or exception.
 */
JSBool JavaObject::invokeJava(JSContext* ctx, SessionData* data,
    const Value& javaThis, int dispId, int numArgs, const jsval* jsargs,
    jsval* rval) {
  HostChannel* channel = data->getHostChannel();
  SessionHandler* handler = data->getSessionHandler();
  scoped_array<Value> args(new Value[numArgs]);
  for (int i = 0; i < numArgs; ++i) {
    data->makeValueFromJsval(args[i], ctx, jsargs[i]);
  }

  bool isException = false;
  Value returnValue;
  if (!InvokeMessage::send(*channel, javaThis, dispId, numArgs, args.get())) {
    Debug::log(Debug::Debugging) << "JavaObject::call failed to send invoke message" << Debug::flush;
  } else {
    Debug::log(Debug::Spam) << " return from invoke" << Debug::flush;
    scoped_ptr<ReturnMessage> retMsg(channel->reactToMessagesWhileWaitingForReturn(handler));
    if (!retMsg.get()) {
      Debug::log(Debug::Debugging) << "JavaObject::call failed to get return value" << Debug::flush;
    } else {
      isException = retMsg->isException();
      returnValue = retMsg->getReturnValue();
    }
  }
  // Since we can set exceptions normally, we always return false to the
  // wrapper function and set the exception ourselves if one occurs.
  // TODO: cleanup exception case
  jsval retvalArray[] = {JSVAL_FALSE, JSVAL_VOID};
  JSObject* retval = JS_NewArrayObject(ctx, 2, retvalArray);
  *rval = OBJECT_TO_JSVAL(retval);
  jsval retJsVal;
  Debug::log(Debug::Spam) << "  result is " << returnValue << Debug::flush;
  data->makeJsvalFromValue(retJsVal, ctx, returnValue);
  if (isException) {
    JS_SetPendingException(ctx, retJsVal);
    return false;
  }
  if (!JS_SetElement(ctx, retval, 1, &retJsVal)) {
    Debug::log(Debug::Error) << "Error setting return value element in array"
        << Debug::flush;
    return false;
  }
  return true;
}
