/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 *
 * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 "WebBindings.h"

#include "V8ArrayBufferView.h"
#include "V8Element.h"
#include "V8Range.h"
#include "WebArrayBuffer.h"
#include "WebArrayBufferView.h"
#include "WebElement.h"
#include "WebRange.h"
#include "bindings/v8/NPV8Object.h"  // for PrivateIdentifier
#include "bindings/v8/ScriptController.h"
#include "bindings/v8/V8DOMWrapper.h"
#include "bindings/v8/V8NPUtils.h"
#include "bindings/v8/custom/V8ArrayBufferCustom.h"
#include "bindings/v8/npruntime_impl.h"
#include "bindings/v8/npruntime_priv.h"
#include "core/dom/Range.h"
#include "core/page/DOMWindow.h"
#include "core/page/Frame.h"
#include "wtf/ArrayBufferView.h"

using namespace WebCore;

namespace WebKit {

bool WebBindings::construct(NPP npp, NPObject* object, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
    return _NPN_Construct(npp, object, args, argCount, result);
}

NPObject* WebBindings::createObject(NPP npp, NPClass* npClass)
{
    return _NPN_CreateObject(npp, npClass);
}

bool WebBindings::enumerate(NPP npp, NPObject* object, NPIdentifier** identifier, uint32_t* identifierCount)
{
    return _NPN_Enumerate(npp, object, identifier, identifierCount);
}

bool WebBindings::evaluate(NPP npp, NPObject* object, NPString* script, NPVariant* result)
{
    return _NPN_Evaluate(npp, object, script, result);
}

bool WebBindings::evaluateHelper(NPP npp, bool popupsAllowed, NPObject* object, NPString* script, NPVariant* result)
{
    return _NPN_EvaluateHelper(npp, popupsAllowed, object, script, result);
}

NPIdentifier WebBindings::getIntIdentifier(int32_t number)
{
    return _NPN_GetIntIdentifier(number);
}

bool WebBindings::getProperty(NPP npp, NPObject* object, NPIdentifier property, NPVariant* result)
{
    return _NPN_GetProperty(npp, object, property, result);
}

NPIdentifier WebBindings::getStringIdentifier(const NPUTF8* string)
{
    return _NPN_GetStringIdentifier(string);
}

void WebBindings::getStringIdentifiers(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers)
{
    _NPN_GetStringIdentifiers(names, nameCount, identifiers);
}

bool WebBindings::hasMethod(NPP npp, NPObject* object, NPIdentifier method)
{
    return _NPN_HasMethod(npp, object, method);
}

bool WebBindings::hasProperty(NPP npp, NPObject* object, NPIdentifier property)
{
    return _NPN_HasProperty(npp, object, property);
}

bool WebBindings::identifierIsString(NPIdentifier identifier)
{
    return _NPN_IdentifierIsString(identifier);
}

int32_t WebBindings::intFromIdentifier(NPIdentifier identifier)
{
    return _NPN_IntFromIdentifier(identifier);
}

void WebBindings::initializeVariantWithStringCopy(NPVariant* variant, const NPString* value)
{
    _NPN_InitializeVariantWithStringCopy(variant, value);
}

bool WebBindings::invoke(NPP npp, NPObject* object, NPIdentifier method, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
    return _NPN_Invoke(npp, object, method, args, argCount, result);
}

bool WebBindings::invokeDefault(NPP npp, NPObject* object, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
    return _NPN_InvokeDefault(npp, object, args, argCount, result);
}

void WebBindings::releaseObject(NPObject* object)
{
    return _NPN_ReleaseObject(object);
}

void WebBindings::releaseVariantValue(NPVariant* variant)
{
    _NPN_ReleaseVariantValue(variant);
}

bool WebBindings::removeProperty(NPP npp, NPObject* object, NPIdentifier identifier)
{
    return _NPN_RemoveProperty(npp, object, identifier);
}

NPObject* WebBindings::retainObject(NPObject* object)
{
    return _NPN_RetainObject(object);
}

void WebBindings::setException(NPObject* object, const NPUTF8* message)
{
    _NPN_SetException(object, message);
}

bool WebBindings::setProperty(NPP npp, NPObject* object, NPIdentifier identifier, const NPVariant* value)
{
    return _NPN_SetProperty(npp, object, identifier, value);
}

void WebBindings::registerObjectOwner(NPP)
{
}

void WebBindings::unregisterObjectOwner(NPP)
{
}

NPP WebBindings::getObjectOwner(NPObject*)
{
    return 0;
}

void WebBindings::unregisterObject(NPObject* object)
{
    _NPN_UnregisterObject(object);
}

NPUTF8* WebBindings::utf8FromIdentifier(NPIdentifier identifier)
{
    return _NPN_UTF8FromIdentifier(identifier);
}

void WebBindings::extractIdentifierData(const NPIdentifier& identifier, const NPUTF8*& string, int32_t& number, bool& isString)
{
    PrivateIdentifier* data = static_cast<PrivateIdentifier*>(identifier);
    if (!data) {
        isString = false;
        number = 0;
        return;
    }

    isString = data->isString;
    if (isString)
        string = data->value.string;
    else
        number = data->value.number;
}

static bool getRangeImpl(NPObject* object, WebRange* webRange, v8::Isolate* isolate)
{
    if (!object)
        return false;

    V8NPObject* v8NPObject = npObjectToV8NPObject(object);
    if (!v8NPObject)
        return false;

    v8::HandleScope handleScope(isolate);
    v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NPObject->v8Object);
    if (v8Object.IsEmpty())
        return false;
    if (!V8Range::info.equals(toWrapperTypeInfo(v8Object)))
        return false;

    Range* native = V8Range::HasInstanceInAnyWorld(v8Object, isolate) ? V8Range::toNative(v8Object) : 0;
    if (!native)
        return false;

    *webRange = WebRange(native);
    return true;
}

static bool getNodeImpl(NPObject* object, WebNode* webNode, v8::Isolate* isolate)
{
    if (!object)
        return false;

    V8NPObject* v8NPObject = npObjectToV8NPObject(object);
    if (!v8NPObject)
        return false;

    v8::HandleScope handleScope(isolate);
    v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NPObject->v8Object);
    if (v8Object.IsEmpty())
        return false;
    Node* native = V8Node::HasInstanceInAnyWorld(v8Object, isolate) ? V8Node::toNative(v8Object) : 0;
    if (!native)
        return false;

    *webNode = WebNode(native);
    return true;
}

static bool getElementImpl(NPObject* object, WebElement* webElement, v8::Isolate* isolate)
{
    if (!object)
        return false;

    V8NPObject* v8NPObject = npObjectToV8NPObject(object);
    if (!v8NPObject)
        return false;

    v8::HandleScope handleScope(isolate);
    v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NPObject->v8Object);
    if (v8Object.IsEmpty())
        return false;
    Element* native = V8Element::HasInstanceInAnyWorld(v8Object, isolate) ? V8Element::toNative(v8Object) : 0;
    if (!native)
        return false;

    *webElement = WebElement(native);
    return true;
}

static bool getArrayBufferImpl(NPObject* object, WebArrayBuffer* arrayBuffer, v8::Isolate* isolate)
{
    if (!object)
        return false;

    V8NPObject* v8NPObject = npObjectToV8NPObject(object);
    if (!v8NPObject)
        return false;

    v8::HandleScope handleScope(isolate);
    v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NPObject->v8Object);
    if (v8Object.IsEmpty())
        return false;
    ArrayBuffer* native = V8ArrayBuffer::HasInstanceInAnyWorld(v8Object, isolate) ? V8ArrayBuffer::toNative(v8Object) : 0;
    if (!native)
        return false;

    *arrayBuffer = WebArrayBuffer(native);
    return true;
}

static bool getArrayBufferViewImpl(NPObject* object, WebArrayBufferView* arrayBufferView, v8::Isolate* isolate)
{
    if (!object)
        return false;

    V8NPObject* v8NPObject = npObjectToV8NPObject(object);
    if (!v8NPObject)
        return false;

    v8::HandleScope handleScope(isolate);
    v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NPObject->v8Object);
    if (v8Object.IsEmpty())
        return false;
    ArrayBufferView* native = V8ArrayBufferView::HasInstanceInAnyWorld(v8Object, isolate) ? V8ArrayBufferView::toNative(v8Object) : 0;
    if (!native)
        return false;

    *arrayBufferView = WebArrayBufferView(native);
    return true;
}

static NPObject* makeIntArrayImpl(const WebVector<int>& data)
{
    v8::HandleScope handleScope;
    v8::Handle<v8::Array> result = v8::Array::New(data.size());
    for (size_t i = 0; i < data.size(); ++i)
        result->Set(i, v8::Number::New(data[i]));

    DOMWindow* window = toDOMWindow(v8::Context::GetCurrent());
    return npCreateV8ScriptObject(0, result, window);
}

static NPObject* makeStringArrayImpl(const WebVector<WebString>& data)
{
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    v8::HandleScope handleScope;
    v8::Handle<v8::Array> result = v8::Array::New(data.size());
    for (size_t i = 0; i < data.size(); ++i)
        result->Set(i, v8String(data[i], isolate));

    DOMWindow* window = toDOMWindow(v8::Context::GetCurrent());
    return npCreateV8ScriptObject(0, result, window);
}

bool WebBindings::getRange(NPObject* range, WebRange* webRange)
{
    return getRangeImpl(range, webRange, v8::Isolate::GetCurrent());
}

bool WebBindings::getArrayBuffer(NPObject* arrayBuffer, WebArrayBuffer* webArrayBuffer)
{
    return getArrayBufferImpl(arrayBuffer, webArrayBuffer, v8::Isolate::GetCurrent());
}

bool WebBindings::getArrayBufferView(NPObject* arrayBufferView, WebArrayBufferView* webArrayBufferView)
{
    return getArrayBufferViewImpl(arrayBufferView, webArrayBufferView, v8::Isolate::GetCurrent());
}

bool WebBindings::getNode(NPObject* node, WebNode* webNode)
{
    return getNodeImpl(node, webNode, v8::Isolate::GetCurrent());
}

bool WebBindings::getElement(NPObject* element, WebElement* webElement)
{
    return getElementImpl(element, webElement, v8::Isolate::GetCurrent());
}

NPObject* WebBindings::makeIntArray(const WebVector<int>& data)
{
    return makeIntArrayImpl(data);
}

NPObject* WebBindings::makeStringArray(const WebVector<WebString>& data)
{
    return makeStringArrayImpl(data);
}

void WebBindings::pushExceptionHandler(ExceptionHandler handler, void* data)
{
    WebCore::pushExceptionHandler(handler, data);
}

void WebBindings::popExceptionHandler()
{
    WebCore::popExceptionHandler();
}

void WebBindings::toNPVariant(v8::Local<v8::Value> object, NPObject* root, NPVariant* result)
{
    WebCore::convertV8ObjectToNPVariant(object, root, result);
}

v8::Handle<v8::Value> WebBindings::toV8Value(const NPVariant* variant)
{
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    if (variant->type == NPVariantType_Object) {
        NPObject* object = NPVARIANT_TO_OBJECT(*variant);
        V8NPObject* v8Object = npObjectToV8NPObject(object);
        if (!v8Object)
            return v8::Undefined();
        return convertNPVariantToV8Object(variant, v8Object->rootObject->frame()->script()->windowScriptNPObject(), isolate);
    }
    // Safe to pass 0 since we have checked the script object class to make sure the
    // argument is a primitive v8 type.
    return convertNPVariantToV8Object(variant, 0, isolate);
}

} // namespace WebKit
