/*
 * Copyright (C) 2008, 2009, 2010 Apple 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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 APPLE INC. ``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 APPLE INC. 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. 
 */

#if USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)

#import "ProxyInstance.h"

#import "NetscapePluginHostProxy.h"
#import "ProxyRuntimeObject.h"
#import <WebCore/IdentifierRep.h>
#import <WebCore/JSDOMWindow.h>
#import <WebCore/npruntime_impl.h>
#import <WebCore/runtime_method.h>
#import <runtime/Error.h>
#import <runtime/FunctionPrototype.h>
#import <runtime/PropertyNameArray.h>

extern "C" {
#import "WebKitPluginHost.h"
}

using namespace JSC;
using namespace JSC::Bindings;
using namespace std;
using namespace WebCore;

namespace WebKit {

class ProxyClass : public JSC::Bindings::Class {
private:
    virtual MethodList methodsNamed(const Identifier&, Instance*) const;
    virtual Field* fieldNamed(const Identifier&, Instance*) const;
};

MethodList ProxyClass::methodsNamed(const Identifier& identifier, Instance* instance) const
{
    return static_cast<ProxyInstance*>(instance)->methodsNamed(identifier);
}

Field* ProxyClass::fieldNamed(const Identifier& identifier, Instance* instance) const
{
    return static_cast<ProxyInstance*>(instance)->fieldNamed(identifier);
}

static ProxyClass* proxyClass()
{
    DEFINE_STATIC_LOCAL(ProxyClass, proxyClass, ());
    return &proxyClass;
}
    
class ProxyField : public JSC::Bindings::Field {
public:
    ProxyField(uint64_t serverIdentifier)
        : m_serverIdentifier(serverIdentifier)
    {
    }
    
    uint64_t serverIdentifier() const { return m_serverIdentifier; }

private:
    virtual JSValue valueFromInstance(ExecState*, const Instance*) const;
    virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const;
    
    uint64_t m_serverIdentifier;
};

JSValue ProxyField::valueFromInstance(ExecState* exec, const Instance* instance) const
{
    return static_cast<const ProxyInstance*>(instance)->fieldValue(exec, this);
}
    
void ProxyField::setValueToInstance(ExecState* exec, const Instance* instance, JSValue value) const
{
    static_cast<const ProxyInstance*>(instance)->setFieldValue(exec, this, value);
}

class ProxyMethod : public JSC::Bindings::Method {
public:
    ProxyMethod(uint64_t serverIdentifier)
        : m_serverIdentifier(serverIdentifier)
    {
    }

    uint64_t serverIdentifier() const { return m_serverIdentifier; }

private:
    virtual int numParameters() const { return 0; }

    uint64_t m_serverIdentifier;
};

ProxyInstance::ProxyInstance(PassRefPtr<RootObject> rootObject, NetscapePluginInstanceProxy* instanceProxy, uint32_t objectID)
    : Instance(rootObject)
    , m_instanceProxy(instanceProxy)
    , m_objectID(objectID)
{
    m_instanceProxy->addInstance(this);
}

ProxyInstance::~ProxyInstance()
{
    deleteAllValues(m_fields);
    deleteAllValues(m_methods);

    if (!m_instanceProxy)
        return;
    
    m_instanceProxy->removeInstance(this);

    invalidate();
}
    
RuntimeObject* ProxyInstance::newRuntimeObject(ExecState* exec)
{
    return new (exec) ProxyRuntimeObject(exec, exec->lexicalGlobalObject(), this);
}

JSC::Bindings::Class* ProxyInstance::getClass() const
{
    return proxyClass();
}

JSValue ProxyInstance::invoke(JSC::ExecState* exec, InvokeType type, uint64_t identifier, const ArgList& args)
{
    if (!m_instanceProxy)
        return jsUndefined();

    RetainPtr<NSData*> arguments(m_instanceProxy->marshalValues(exec, args));

    uint32_t requestID = m_instanceProxy->nextRequestID();

    for (unsigned i = 0; i < args.size(); i++)
        m_instanceProxy->retainLocalObject(args.at(i));

    if (_WKPHNPObjectInvoke(m_instanceProxy->hostProxy()->port(), m_instanceProxy->pluginID(), requestID, m_objectID,
                            type, identifier, (char*)[arguments.get() bytes], [arguments.get() length]) != KERN_SUCCESS) {
        if (m_instanceProxy) {
            for (unsigned i = 0; i < args.size(); i++)
                m_instanceProxy->releaseLocalObject(args.at(i));
        }
        return jsUndefined();
    }
    
    auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID);
    NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(exec);

    if (m_instanceProxy) {
        for (unsigned i = 0; i < args.size(); i++)
            m_instanceProxy->releaseLocalObject(args.at(i));
    }

    if (!reply.get() || !reply->m_returnValue)
        return jsUndefined();
    
    return m_instanceProxy->demarshalValue(exec, (char*)CFDataGetBytePtr(reply->m_result.get()), CFDataGetLength(reply->m_result.get()));
}

class ProxyRuntimeMethod : public RuntimeMethod {
public:
    ProxyRuntimeMethod(ExecState* exec, JSGlobalObject* globalObject, const Identifier& name, Bindings::MethodList& list)
        // FIXME: deprecatedGetDOMStructure uses the prototype off of the wrong global object
        // exec-globalData() is also likely wrong.
        : RuntimeMethod(exec, globalObject, deprecatedGetDOMStructure<ProxyRuntimeMethod>(exec), name, list)
    {
        ASSERT(inherits(&s_info));
    }

    static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
    {
        return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
    }

    static const ClassInfo s_info;
};

const ClassInfo ProxyRuntimeMethod::s_info = { "ProxyRuntimeMethod", &RuntimeMethod::s_info, 0, 0 };

JSValue ProxyInstance::getMethod(JSC::ExecState* exec, const JSC::Identifier& propertyName)
{
    MethodList methodList = getClass()->methodsNamed(propertyName, this);
    return new (exec) ProxyRuntimeMethod(exec, exec->lexicalGlobalObject(), propertyName, methodList);
}

JSValue ProxyInstance::invokeMethod(ExecState* exec, JSC::RuntimeMethod* runtimeMethod)
{
    if (!asObject(runtimeMethod)->inherits(&ProxyRuntimeMethod::s_info))
        return throwError(exec, createTypeError(exec, "Attempt to invoke non-plug-in method on plug-in object."));

    const MethodList& methodList = *runtimeMethod->methods();

    ASSERT(methodList.size() == 1);

    ProxyMethod* method = static_cast<ProxyMethod*>(methodList[0]);

    return invoke(exec, Invoke, method->serverIdentifier(), ArgList(exec));
}

bool ProxyInstance::supportsInvokeDefaultMethod() const
{
    if (!m_instanceProxy)
        return false;
    
    uint32_t requestID = m_instanceProxy->nextRequestID();
    
    if (_WKPHNPObjectHasInvokeDefaultMethod(m_instanceProxy->hostProxy()->port(),
                                            m_instanceProxy->pluginID(), requestID,
                                            m_objectID) != KERN_SUCCESS)
        return false;
    
    auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
    if (reply.get() && reply->m_result)
        return true;
        
    return false;
}

JSValue ProxyInstance::invokeDefaultMethod(ExecState* exec)
{
    return invoke(exec, InvokeDefault, 0, ArgList(exec));
}

bool ProxyInstance::supportsConstruct() const
{
    if (!m_instanceProxy)
        return false;
    
    uint32_t requestID = m_instanceProxy->nextRequestID();
    
    if (_WKPHNPObjectHasConstructMethod(m_instanceProxy->hostProxy()->port(),
                                        m_instanceProxy->pluginID(), requestID,
                                        m_objectID) != KERN_SUCCESS)
        return false;
    
    auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
    if (reply.get() && reply->m_result)
        return true;
        
    return false;
}
    
JSValue ProxyInstance::invokeConstruct(ExecState* exec, const ArgList& args)
{
    return invoke(exec, Construct, 0, args);
}

JSValue ProxyInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
{
    if (hint == PreferString)
        return stringValue(exec);
    if (hint == PreferNumber)
        return numberValue(exec);
    return valueOf(exec);
}

JSValue ProxyInstance::stringValue(ExecState* exec) const
{
    // FIXME: Implement something sensible.
    return jsEmptyString(exec);
}

JSValue ProxyInstance::numberValue(ExecState*) const
{
    // FIXME: Implement something sensible.
    return jsNumber(0);
}

JSValue ProxyInstance::booleanValue() const
{
    // FIXME: Implement something sensible.
    return jsBoolean(false);
}

JSValue ProxyInstance::valueOf(ExecState* exec) const
{
    return stringValue(exec);
}

void ProxyInstance::getPropertyNames(ExecState* exec, PropertyNameArray& nameArray)
{
    if (!m_instanceProxy)
        return;
    
    uint32_t requestID = m_instanceProxy->nextRequestID();
    
    if (_WKPHNPObjectEnumerate(m_instanceProxy->hostProxy()->port(), m_instanceProxy->pluginID(), requestID, m_objectID) != KERN_SUCCESS)
        return;
    
    auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID);
    NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(exec);
    if (!reply.get() || !reply->m_returnValue)
        return;
    
    RetainPtr<NSArray*> array = [NSPropertyListSerialization propertyListFromData:(NSData *)reply->m_result.get()
                                                                 mutabilityOption:NSPropertyListImmutable
                                                                           format:0
                                                                 errorDescription:0];
    
    for (NSNumber *number in array.get()) {
        IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>([number longLongValue]);
        if (!IdentifierRep::isValid(identifier))
            continue;

        if (identifier->isString()) {
            const char* str = identifier->string();
            nameArray.add(Identifier(JSDOMWindow::commonJSGlobalData(), stringToUString(String::fromUTF8WithLatin1Fallback(str, strlen(str)))));
        } else
            nameArray.add(Identifier::from(exec, identifier->number()));
    }
}

MethodList ProxyInstance::methodsNamed(const Identifier& identifier)
{
    if (!m_instanceProxy)
        return MethodList();
    
    // If we already have an entry in the map, use it.
    MethodMap::iterator existingMapEntry = m_methods.find(identifier.impl());
    if (existingMapEntry != m_methods.end()) {
        MethodList methodList;
        if (existingMapEntry->second)
            methodList.append(existingMapEntry->second);
        return methodList;
    }
    
    uint64_t methodName = reinterpret_cast<uint64_t>(_NPN_GetStringIdentifier(identifier.ascii().data()));
    uint32_t requestID = m_instanceProxy->nextRequestID();
    
    if (_WKPHNPObjectHasMethod(m_instanceProxy->hostProxy()->port(),
                               m_instanceProxy->pluginID(), requestID,
                               m_objectID, methodName) != KERN_SUCCESS)
        return MethodList();
    
    auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
    if (!reply.get())
        return MethodList();

    if (!reply->m_result && !m_instanceProxy->hostProxy()->shouldCacheMissingPropertiesAndMethods())
        return MethodList();

    // Add a new entry to the map unless an entry was added while we were in waitForReply.
    pair<MethodMap::iterator, bool> mapAddResult = m_methods.add(identifier.impl(), 0);
    if (mapAddResult.second && reply->m_result)
        mapAddResult.first->second = new ProxyMethod(methodName);

    MethodList methodList;
    if (mapAddResult.first->second)
        methodList.append(mapAddResult.first->second);
    return methodList;
}

Field* ProxyInstance::fieldNamed(const Identifier& identifier)
{
    if (!m_instanceProxy)
        return 0;
    
    // If we already have an entry in the map, use it.
    FieldMap::iterator existingMapEntry = m_fields.find(identifier.impl());
    if (existingMapEntry != m_fields.end())
        return existingMapEntry->second;
    
    uint64_t propertyName = reinterpret_cast<uint64_t>(_NPN_GetStringIdentifier(identifier.ascii().data()));
    uint32_t requestID = m_instanceProxy->nextRequestID();
    
    if (_WKPHNPObjectHasProperty(m_instanceProxy->hostProxy()->port(),
                                 m_instanceProxy->pluginID(), requestID,
                                 m_objectID, propertyName) != KERN_SUCCESS)
        return 0;
    
    auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
    if (!reply.get())
        return 0;
    
    if (!reply->m_result && !m_instanceProxy->hostProxy()->shouldCacheMissingPropertiesAndMethods())
        return 0;
    
    // Add a new entry to the map unless an entry was added while we were in waitForReply.
    pair<FieldMap::iterator, bool> mapAddResult = m_fields.add(identifier.impl(), 0);
    if (mapAddResult.second && reply->m_result)
        mapAddResult.first->second = new ProxyField(propertyName);
    return mapAddResult.first->second;
}

JSC::JSValue ProxyInstance::fieldValue(ExecState* exec, const Field* field) const
{
    if (!m_instanceProxy)
        return jsUndefined();
    
    uint64_t serverIdentifier = static_cast<const ProxyField*>(field)->serverIdentifier();
    uint32_t requestID = m_instanceProxy->nextRequestID();
    
    if (_WKPHNPObjectGetProperty(m_instanceProxy->hostProxy()->port(),
                                 m_instanceProxy->pluginID(), requestID,
                                 m_objectID, serverIdentifier) != KERN_SUCCESS)
        return jsUndefined();
    
    auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID);
    NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(exec);
    if (!reply.get() || !reply->m_returnValue)
        return jsUndefined();
    
    return m_instanceProxy->demarshalValue(exec, (char*)CFDataGetBytePtr(reply->m_result.get()), CFDataGetLength(reply->m_result.get()));
}
    
void ProxyInstance::setFieldValue(ExecState* exec, const Field* field, JSValue value) const
{
    if (!m_instanceProxy)
        return;
    
    uint64_t serverIdentifier = static_cast<const ProxyField*>(field)->serverIdentifier();
    uint32_t requestID = m_instanceProxy->nextRequestID();
    
    data_t valueData;
    mach_msg_type_number_t valueLength;

    m_instanceProxy->marshalValue(exec, value, valueData, valueLength);
    m_instanceProxy->retainLocalObject(value);
    kern_return_t kr = _WKPHNPObjectSetProperty(m_instanceProxy->hostProxy()->port(),
                                                m_instanceProxy->pluginID(), requestID,
                                                m_objectID, serverIdentifier, valueData, valueLength);
    mig_deallocate(reinterpret_cast<vm_address_t>(valueData), valueLength);
    if (m_instanceProxy)
        m_instanceProxy->releaseLocalObject(value);
    if (kr != KERN_SUCCESS)
        return;
    
    auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
    NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(exec);
}

void ProxyInstance::invalidate()
{
    ASSERT(m_instanceProxy);
    
    if (NetscapePluginHostProxy* hostProxy = m_instanceProxy->hostProxy())
        _WKPHNPObjectRelease(hostProxy->port(),
                             m_instanceProxy->pluginID(), m_objectID);
    m_instanceProxy = 0;
}

} // namespace WebKit

#endif // USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)

