/*
 * 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 "Debug.h"

#include "JavaObject.h"
#include "Plugin.h"
#include "NPVariantWrapper.h"

using std::string;

static string IdentifierName(NPIdentifier name) {
  string iname;
  if (NPN_IdentifierIsString(name)) {
    iname = NPN_UTF8FromIdentifier(name);
  } else {
    char buf[50];
    snprintf(buf, sizeof(buf), "%d", NPN_IntFromIdentifier(name));
    iname = buf;
  }
  return iname;
}

JavaObject* JavaObject::create(ScriptableInstance* plugin, int id) {
  Debug::log(Debug::Spam) << "Creating Java object id=" << id;
  NPClass* npClass = GetNPClass<JavaObject>();
  NPObject* obj = NPN_CreateObject(plugin->getNPP(), npClass);
  Debug::log(Debug::Spam) << " addr=" << obj << Debug::flush;
  JavaObject* jObj = static_cast<JavaObject*>(obj);
  jObj->setObjectId(id);
  return jObj;
}

bool JavaObject::isInstance(NPObject* obj) {
  return obj->_class == GetNPClass<JavaObject>();
}

JavaObject::~JavaObject() {
  if (plugin) {
    plugin->destroyJavaWrapper(this);
  } else {
    Debug::log(Debug::Spam) << "Destroying JavaObject " << objectId << " after plugin destroyed"
        << Debug::flush;
  }
}

bool JavaObject::enumeration(NPIdentifier** propReturn, uint32_t* count) {
  Debug::log(Debug::Debugging) << "JavaObject::enumeration(" << objectId << ")"
      << Debug::flush;
  int n = 1;
  NPIdentifier* props = static_cast<NPIdentifier*>(NPN_MemAlloc(sizeof(NPIdentifier) * n));
  props[0] = idID;
  *propReturn = props;
  *count = n;
  return true;
}

bool JavaObject::getProperty(NPIdentifier prop, NPVariant *result) {
  if (!plugin) {
    Debug::log(Debug::Spam) << "Ignoring getProperty on " << objectId << " after plugin destroyed"
        << Debug::flush;
    VOID_TO_NPVARIANT(*result);
    return true;
  }
  Debug::log(Debug::Spam) << "JavaObject::getProperty(" << objectId << ")" << Debug::flush;
  if (NPN_IdentifierIsString(prop)) {
    if (prop == plugin->toStringID) {
      return plugin->JavaObject_getToStringTearOff(result);
    }
    if (prop == idID) {
      INT32_TO_NPVARIANT(objectId, *result);
      return true;
    }
    // all other properties are numeric dispatchIDs
    return false;
  }
  int dispId = NPN_IntFromIdentifier(prop);
  // JavaObject_getProperty will retain the return value if needed.
  return plugin->JavaObject_getProperty(objectId, dispId, result);
}

bool JavaObject::hasMethod(NPIdentifier method) {
  if (!plugin) {
    Debug::log(Debug::Spam) << "Ignoring hasMethod on " << objectId << " after plugin destroyed"
        << Debug::flush;
    return true;
  }
  Debug::log(Debug::Spam) << "JavaObject::hasMethod(" << objectId << ", method="
      << IdentifierName(method) << ")" << Debug::flush;
  return false;
//  return !NPN_IdentifierIsString(method);
}

bool JavaObject::hasProperty(NPIdentifier prop) {
  if (!plugin) {
    Debug::log(Debug::Spam) << "Ignoring hasProperty on " << objectId << " after plugin destroyed"
        << Debug::flush;
    return true;
  }
  Debug::log(Debug::Spam) << "JavaObject::hasProperty(" << objectId << ", prop="
      << IdentifierName(prop) << ")" << Debug::flush;
  return !NPN_IdentifierIsString(prop) || prop == idID || prop == plugin->toStringID;
}

bool JavaObject::invokeDefault(const NPVariant *args, uint32_t argCount, NPVariant *result) {
  if (argCount < 2 || !NPVariantProxy::isInt(args[0])
      || (!NPVariantProxy::isNull(args[1]) && !NPVariantProxy::isObject(args[1]))) {
    Debug::log(Debug::Error) << "incorrect arguments to invokeDefault" << Debug::flush;
    return false;
  }
  if (!plugin) {
    Debug::log(Debug::Spam) << "Ignoring invokeDefault on " << objectId << " after plugin destroyed"
        << Debug::flush;
    VOID_TO_NPVARIANT(*result);
    return true;
  }
  Debug::log(Debug::Debugging) << "JavaObject::invokeDefault(" << objectId;
  for (uint32_t i = 0; i < argCount; ++i) {
    Debug::log(Debug::Debugging) << ", " << NPVariantProxy::toString(args[i]);
  }
  Debug::log(Debug::Debugging) << ")" << Debug::flush;
  int dispId = NPVariantProxy::getAsInt(args[0]);
  int objId = objectId;
  if (!NPVariantProxy::isNull(args[1])) {
    NPObject* thisObj = NPVariantProxy::getAsObject(args[1]);
    if (isInstance(thisObj)) {
      JavaObject* thisJavaObj = static_cast<JavaObject*>(thisObj);
      objId = thisJavaObj->objectId;
    }
  }
  // JavaObject_invoke will retain the return value if needed.
  return plugin->JavaObject_invoke(objId, dispId, args + 2, argCount - 2, result);
}

bool JavaObject::invoke(NPIdentifier name, const NPVariant *args,
    uint32_t argCount, NPVariant *result) {
  VOID_TO_NPVARIANT(*result);
  if (!plugin) {
    Debug::log(Debug::Spam) << "Ignoring invoke on " << objectId << " after plugin destroyed"
        << Debug::flush;
    return true;
  }
  string methodName(NPN_UTF8FromIdentifier(name));
  Debug::log(Debug::Spam) << "JavaObject::invoke(" << objectId << ", method="
      << methodName << ")" << Debug::flush;
  if (name == plugin->toStringID) {
    // -1 is magic and means a raw toString().
    return plugin->JavaObject_invoke(objectId, -1, args, argCount, result);
  }
  // toString is the only method we support invoking directly on a Java wrapper
  return false;
}

bool JavaObject::setProperty(NPIdentifier prop, const NPVariant *value) {
  if (!plugin) {
    Debug::log(Debug::Spam) << "Ignoring setProperty on " << objectId << " after plugin destroyed"
        << Debug::flush;
    return true;
  }
  Debug::log(Debug::Spam) << "JavaObject::setProperty(" << objectId << ", val="
      << NPVariantProxy::toString(*value) << ")" << Debug::flush;
  if (NPN_IdentifierIsString(prop)) {
    // any non-numeric properties are read-only
    return false;
  }
  int dispId = NPN_IntFromIdentifier(prop); 
  return plugin->JavaObject_setProperty(objectId, dispId, value);
}
