/*
 * Copyright 2010, The Android Open Source Project
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


#include "config.h"
#include "JavaNPObjectV8.h"

#if ENABLE(JAVA_BRIDGE)

#include "JNIUtilityPrivate.h"
#include "JavaClassV8.h"
#include "JavaFieldV8.h"
#include "JavaInstanceV8.h"
#include "JavaMethod.h"
#include "JavaValueV8.h"
#include "npruntime_impl.h"

namespace JSC {

namespace Bindings {

static NPObject* AllocJavaNPObject(NPP, NPClass*)
{
    JavaNPObject* obj = static_cast<JavaNPObject*>(malloc(sizeof(JavaNPObject)));
    if (!obj)
        return 0;
    memset(obj, 0, sizeof(JavaNPObject));
    return reinterpret_cast<NPObject*>(obj);
}

static void FreeJavaNPObject(NPObject* npobj)
{
    JavaNPObject* obj = reinterpret_cast<JavaNPObject*>(npobj);
    obj->m_instance = 0; // free does not call the destructor
    free(obj);
}

static NPClass JavaNPObjectClass = {
    NP_CLASS_STRUCT_VERSION,
    AllocJavaNPObject, // allocate,
    FreeJavaNPObject, // free,
    0, // invalidate
    JavaNPObjectHasMethod,
    JavaNPObjectInvoke,
    0, // invokeDefault,
    JavaNPObjectHasProperty,
    JavaNPObjectGetProperty,
    0, // setProperty
    0, // removeProperty
    0, // enumerate
    0 // construct
};

NPObject* JavaInstanceToNPObject(JavaInstance* instance)
{
    JavaNPObject* object = reinterpret_cast<JavaNPObject*>(_NPN_CreateObject(0, &JavaNPObjectClass));
    object->m_instance = instance;
    return reinterpret_cast<NPObject*>(object);
}

// Returns null if obj is not a wrapper of JavaInstance
JavaInstance* ExtractJavaInstance(NPObject* obj)
{
    if (obj->_class == &JavaNPObjectClass)
        return reinterpret_cast<JavaNPObject*>(obj)->m_instance.get();
    return 0;
}

bool JavaNPObjectHasMethod(NPObject* obj, NPIdentifier identifier)
{
    JavaInstance* instance = ExtractJavaInstance(obj);
    if (!instance)
        return false;
    NPUTF8* name = _NPN_UTF8FromIdentifier(identifier);
    if (!name)
        return false;

    instance->begin();
    bool result = (instance->getClass()->methodsNamed(name).size() > 0);
    instance->end();

    // TODO: use NPN_MemFree
    free(name);

    return result;
}

bool JavaNPObjectInvoke(NPObject* obj, NPIdentifier identifier, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
    JavaInstance* instance = ExtractJavaInstance(obj);
    if (!instance)
        return false;
    NPUTF8* name = _NPN_UTF8FromIdentifier(identifier);
    if (!name)
        return false;

    instance->begin();

    MethodList methodList = instance->getClass()->methodsNamed(name);
    // TODO: use NPN_MemFree
    free(name);

    // Try to find a good match for the overloaded method. The
    // fundamental problem is that JavaScript doesn't have the
    // notion of method overloading and Java does. We could
    // get a bit more sophisticated and attempt to do some
    // type checking as well as checking the number of parameters.
    size_t numMethods = methodList.size();
    JavaMethod* aMethod;
    JavaMethod* jMethod = 0;
    for (size_t methodIndex = 0; methodIndex < numMethods; methodIndex++) {
        aMethod = methodList[methodIndex];
        if (aMethod->numParameters() == static_cast<int>(argCount)) {
            jMethod = aMethod;
            break;
        }
    }
    if (!jMethod) {
        instance->end();
        return false;
    }

    JavaValue* jArgs = new JavaValue[argCount];
    for (unsigned int i = 0; i < argCount; i++)
        jArgs[i] = convertNPVariantToJavaValue(args[i], jMethod->parameterAt(i));

// ANDROID
    bool exceptionOccurred;
    JavaValue jResult = instance->invokeMethod(jMethod, jArgs, exceptionOccurred);
    instance->end();
    delete[] jArgs;

    if (exceptionOccurred)
        return false;
// END ANDROID

    VOID_TO_NPVARIANT(*result);
    convertJavaValueToNPVariant(jResult, result);
    return true;
}

bool JavaNPObjectHasProperty(NPObject* obj, NPIdentifier identifier)
{
    JavaInstance* instance = ExtractJavaInstance(obj);
    if (!instance)
        return false;
    NPUTF8* name = _NPN_UTF8FromIdentifier(identifier);
    if (!name)
        return false;
    instance->begin();
    bool result = instance->getClass()->fieldNamed(name);
    instance->end();
    free(name);
    return result;
}

bool JavaNPObjectGetProperty(NPObject* obj, NPIdentifier identifier, NPVariant* result)
{
    VOID_TO_NPVARIANT(*result);
    JavaInstance* instance = ExtractJavaInstance(obj);
    if (!instance)
        return false;
    NPUTF8* name = _NPN_UTF8FromIdentifier(identifier);
    if (!name)
        return false;

    instance->begin();
    JavaField* field = instance->getClass()->fieldNamed(name);
    free(name); // TODO: use NPN_MemFree
    if (!field) {
        instance->end();
        return false;
    }

#if PLATFORM(ANDROID)
    // JSC does not seem to support returning object properties so we emulate that
    // behaviour here.
    JavaValue value;
#else
    JavaValue value = instance->getField(field);
#endif // PLATFORM(ANDROID)
    instance->end();

    convertJavaValueToNPVariant(value, result);

    return true;
}

} // namespace Bindings

} // namespace JSC

#endif // ENABLE(JAVA_BRIDGE)
