/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 * Copyright (C) 2009 Pawel Hajdan (phajdan.jr@chromium.org)
 *
 * 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.
 */

// This file contains definitions for CppBoundClass

// Here's the control flow of a JS method getting forwarded to a class.
// - Something calls our NPObject with a function like "Invoke".
// - CppNPObject's static invoke() function forwards it to its attached
//   CppBoundClass's invoke() method.
// - CppBoundClass has then overridden invoke() to look up the function
//   name in its internal map of methods, and then calls the appropriate
//   method.

#include "CppBoundClass.h"

#include "TestCommon.h"
#include "public/platform/WebString.h"
#include "public/web/WebBindings.h"
#include "public/web/WebFrame.h"
#include <memory>

using namespace WebKit;
using namespace std;

namespace WebTestRunner {

namespace {

class CppVariantPropertyCallback : public CppBoundClass::PropertyCallback {
public:
    CppVariantPropertyCallback(CppVariant* value) : m_value(value) { }

    virtual bool getValue(CppVariant* value)
    {
        value->set(*m_value);
        return true;
    }

    virtual bool setValue(const CppVariant& value)
    {
        m_value->set(value);
        return true;
    }

private:
    CppVariant* m_value;
};

class GetterPropertyCallback : public CppBoundClass::PropertyCallback {
public:
    GetterPropertyCallback(auto_ptr<CppBoundClass::GetterCallback> callback)
        : m_callback(callback)
    {
    }

    virtual bool getValue(CppVariant* value)
    {
        m_callback->run(value);
        return true;
    }

    virtual bool setValue(const CppVariant& value) { return false; }

private:
    auto_ptr<CppBoundClass::GetterCallback> m_callback;
};

}

// Our special NPObject type. We extend an NPObject with a pointer to a
// CppBoundClass, which is just a C++ interface that we forward all NPObject
// callbacks to.
struct CppNPObject {
    NPObject parent; // This must be the first field in the struct.
    CppBoundClass* boundClass;

    //
    // All following objects and functions are static, and just used to interface
    // with NPObject/NPClass.
    //

    // An NPClass associates static functions of CppNPObject with the
    // function pointers used by the JS runtime.
    static NPClass npClass;

    // Allocate a new NPObject with the specified class.
    static NPObject* allocate(NPP, NPClass*);

    // Free an object.
    static void deallocate(NPObject*);

    // Returns true if the C++ class associated with this NPObject exposes the
    // given property. Called by the JS runtime.
    static bool hasProperty(NPObject*, NPIdentifier);

    // Returns true if the C++ class associated with this NPObject exposes the
    // given method. Called by the JS runtime.
    static bool hasMethod(NPObject*, NPIdentifier);

    // If the given method is exposed by the C++ class associated with this
    // NPObject, invokes it with the given arguments and returns a result. Otherwise,
    // returns "undefined" (in the JavaScript sense). Called by the JS runtime.
    static bool invoke(NPObject*, NPIdentifier,
                       const NPVariant* arguments, uint32_t argumentCount,
                       NPVariant* result);

    // If the given property is exposed by the C++ class associated with this
    // NPObject, returns its value. Otherwise, returns "undefined" (in the
    // JavaScript sense). Called by the JS runtime.
    static bool getProperty(NPObject*, NPIdentifier, NPVariant* result);

    // If the given property is exposed by the C++ class associated with this
    // NPObject, sets its value. Otherwise, does nothing. Called by the JS
    // runtime.
    static bool setProperty(NPObject*, NPIdentifier, const NPVariant* value);
};

// Build CppNPObject's static function pointers into an NPClass, for use
// in constructing NPObjects for the C++ classes.
NPClass CppNPObject::npClass = {
    NP_CLASS_STRUCT_VERSION,
    CppNPObject::allocate,
    CppNPObject::deallocate,
    /* NPInvalidateFunctionPtr */ 0,
    CppNPObject::hasMethod,
    CppNPObject::invoke,
    /* NPInvokeDefaultFunctionPtr */ 0,
    CppNPObject::hasProperty,
    CppNPObject::getProperty,
    CppNPObject::setProperty,
    /* NPRemovePropertyFunctionPtr */ 0
};

NPObject* CppNPObject::allocate(NPP npp, NPClass* aClass)
{
    CppNPObject* obj = new CppNPObject;
    // obj->parent will be initialized by the NPObject code calling this.
    obj->boundClass = 0;
    return &obj->parent;
}

void CppNPObject::deallocate(NPObject* npObj)
{
    CppNPObject* obj = reinterpret_cast<CppNPObject*>(npObj);
    delete obj;
}

bool CppNPObject::hasMethod(NPObject* npObj, NPIdentifier ident)
{
    CppNPObject* obj = reinterpret_cast<CppNPObject*>(npObj);
    return obj->boundClass->hasMethod(ident);
}

bool CppNPObject::hasProperty(NPObject* npObj, NPIdentifier ident)
{
    CppNPObject* obj = reinterpret_cast<CppNPObject*>(npObj);
    return obj->boundClass->hasProperty(ident);
}

bool CppNPObject::invoke(NPObject* npObj, NPIdentifier ident,
                         const NPVariant* arguments, uint32_t argumentCount,
                         NPVariant* result)
{
    CppNPObject* obj = reinterpret_cast<CppNPObject*>(npObj);
    return obj->boundClass->invoke(ident, arguments, argumentCount, result);
}

bool CppNPObject::getProperty(NPObject* npObj, NPIdentifier ident, NPVariant* result)
{
    CppNPObject* obj = reinterpret_cast<CppNPObject*>(npObj);
    return obj->boundClass->getProperty(ident, result);
}

bool CppNPObject::setProperty(NPObject* npObj, NPIdentifier ident, const NPVariant* value)
{
    CppNPObject* obj = reinterpret_cast<CppNPObject*>(npObj);
    return obj->boundClass->setProperty(ident, value);
}

CppBoundClass::~CppBoundClass()
{
    for (MethodList::iterator i = m_methods.begin(); i != m_methods.end(); ++i)
        delete i->second;

    for (PropertyList::iterator i = m_properties.begin(); i != m_properties.end(); ++i)
        delete i->second;

    // Unregister ourselves if we were bound to a frame.
    if (m_boundToFrame)
        WebBindings::unregisterObject(NPVARIANT_TO_OBJECT(m_selfVariant));
}

bool CppBoundClass::hasMethod(NPIdentifier ident) const
{
    return m_methods.find(ident) != m_methods.end();
}

bool CppBoundClass::hasProperty(NPIdentifier ident) const
{
    return m_properties.find(ident) != m_properties.end();
}

bool CppBoundClass::invoke(NPIdentifier ident,
                           const NPVariant* arguments,
                           size_t argumentCount,
                           NPVariant* result) {
    MethodList::const_iterator end = m_methods.end();
    MethodList::const_iterator method = m_methods.find(ident);
    Callback* callback;
    if (method == end) {
        if (!m_fallbackCallback.get()) {
            VOID_TO_NPVARIANT(*result);
            return false;
        }
        callback = m_fallbackCallback.get();
    } else
        callback = (*method).second;

    // Build a CppArgumentList argument vector from the NPVariants coming in.
    CppArgumentList cppArguments(argumentCount);
    for (size_t i = 0; i < argumentCount; i++)
        cppArguments[i].set(arguments[i]);

    CppVariant cppResult;
    callback->run(cppArguments, &cppResult);

    cppResult.copyToNPVariant(result);
    return true;
}

bool CppBoundClass::getProperty(NPIdentifier ident, NPVariant* result) const
{
    PropertyList::const_iterator callback = m_properties.find(ident);
    if (callback == m_properties.end()) {
        VOID_TO_NPVARIANT(*result);
        return false;
    }

    CppVariant cppValue;
    if (!callback->second->getValue(&cppValue))
        return false;
    cppValue.copyToNPVariant(result);
    return true;
}

bool CppBoundClass::setProperty(NPIdentifier ident, const NPVariant* value)
{
    PropertyList::iterator callback = m_properties.find(ident);
    if (callback == m_properties.end())
        return false;

    CppVariant cppValue;
    cppValue.set(*value);
    return (*callback).second->setValue(cppValue);
}

void CppBoundClass::bindCallback(const string& name, Callback* callback)
{
    NPIdentifier ident = WebBindings::getStringIdentifier(name.c_str());
    MethodList::iterator oldCallback = m_methods.find(ident);
    if (oldCallback != m_methods.end()) {
        delete oldCallback->second;
        if (!callback) {
            m_methods.erase(oldCallback);
            return;
        }
    }

    m_methods[ident] = callback;
}

void CppBoundClass::bindGetterCallback(const string& name, auto_ptr<GetterCallback> callback)
{
    PropertyCallback* propertyCallback = callback.get() ? new GetterPropertyCallback(callback) : 0;
    bindProperty(name, propertyCallback);
}

void CppBoundClass::bindProperty(const string& name, CppVariant* prop)
{
    PropertyCallback* propertyCallback = prop ? new CppVariantPropertyCallback(prop) : 0;
    bindProperty(name, propertyCallback);
}

void CppBoundClass::bindProperty(const string& name, PropertyCallback* callback)
{
    NPIdentifier ident = WebBindings::getStringIdentifier(name.c_str());
    PropertyList::iterator oldCallback = m_properties.find(ident);
    if (oldCallback != m_properties.end()) {
        delete oldCallback->second;
        if (!callback) {
            m_properties.erase(oldCallback);
            return;
        }
    }

    m_properties[ident] = callback;
}

bool CppBoundClass::isMethodRegistered(const string& name) const
{
    NPIdentifier ident = WebBindings::getStringIdentifier(name.c_str());
    MethodList::const_iterator callback = m_methods.find(ident);
    return callback != m_methods.end();
}

CppVariant* CppBoundClass::getAsCppVariant()
{
    if (!m_selfVariant.isObject()) {
        // Create an NPObject using our static NPClass. The first argument (a
        // plugin's instance handle) is passed through to the allocate function
        // directly, and we don't use it, so it's ok to be 0.
        NPObject* npObj = WebBindings::createObject(0, &CppNPObject::npClass);
        CppNPObject* obj = reinterpret_cast<CppNPObject*>(npObj);
        obj->boundClass = this;
        m_selfVariant.set(npObj);
        WebBindings::releaseObject(npObj); // CppVariant takes the reference.
    }
    WEBKIT_ASSERT(m_selfVariant.isObject());
    return &m_selfVariant;
}

void CppBoundClass::bindToJavascript(WebFrame* frame, const WebString& classname)
{
    // BindToWindowObject will take its own reference to the NPObject, and clean
    // up after itself. It will also (indirectly) register the object with V8,
    // so we must remember this so we can unregister it when we're destroyed.
    frame->bindToWindowObject(classname, NPVARIANT_TO_OBJECT(*getAsCppVariant()), 0);
    m_boundToFrame = true;
}

}
