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

using namespace blink;
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.
    }
    BLINK_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;
}

}
