/*
 * Copyright (C) 2004, 2006 Apple Computer, Inc.  All rights reserved.
 * Copyright (C) 2007, 2008, 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:
 * 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 COMPUTER, 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 COMPUTER, 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.
 */

#include "config.h"

#include "NPV8Object.h"

#include "PlatformSupport.h"
#include "DOMWindow.h"
#include "Frame.h"
#include "NPObjectWrapper.h"
#include <wtf/OwnArrayPtr.h>
#include "PlatformString.h"
#include "ScriptSourceCode.h"
#include "UserGestureIndicator.h"
#include "V8Binding.h"
#include "V8GCController.h"
#include "V8NPUtils.h"
#include "WrapperTypeInfo.h"
#include "npruntime_impl.h"
#include "npruntime_priv.h"

#include <stdio.h>
#include <wtf/StringExtras.h>

using namespace WebCore;

namespace WebCore {

WrapperTypeInfo* npObjectTypeInfo()
{
    static WrapperTypeInfo typeInfo = { 0, 0, 0, 0, 0, WrapperTypeObjectPrototype };
    return &typeInfo;
}

typedef Vector<V8NPObject*> V8NPObjectVector;
typedef HashMap<int, V8NPObjectVector> V8NPObjectMap;

static v8::Local<v8::Context> toV8Context(NPP npp, NPObject* npObject)
{
    V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject);
    DOMWindow* window = object->rootObject;
    if (!window || !window->isCurrentlyDisplayedInFrame())
        return v8::Local<v8::Context>();
    return ScriptController::mainWorldContext(object->rootObject->frame());
}

static V8NPObjectMap* staticV8NPObjectMap()
{
    DEFINE_STATIC_LOCAL(V8NPObjectMap, v8npObjectMap, ());
    return &v8npObjectMap;
}

// FIXME: Comments on why use malloc and free.
static NPObject* allocV8NPObject(NPP, NPClass*)
{
    return static_cast<NPObject*>(malloc(sizeof(V8NPObject)));
}

static void freeV8NPObject(NPObject* npObject)
{
    V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject);
    if (int v8ObjectHash = v8NpObject->v8Object->GetIdentityHash()) {
        V8NPObjectMap::iterator iter = staticV8NPObjectMap()->find(v8ObjectHash);
        if (iter != staticV8NPObjectMap()->end()) {
            V8NPObjectVector& objects = iter->second;
            for (size_t index = 0; index < objects.size(); ++index) {
                if (objects.at(index) == v8NpObject) {
                    objects.remove(index);
                    break;
                }
            }
            if (objects.isEmpty())
                staticV8NPObjectMap()->remove(v8ObjectHash);
        } else
            ASSERT_NOT_REACHED();
    } else {
        ASSERT(!v8::Context::InContext());
        staticV8NPObjectMap()->clear();
    }

#ifndef NDEBUG
    V8GCController::unregisterGlobalHandle(v8NpObject, v8NpObject->v8Object);
#endif
    v8NpObject->v8Object.Dispose();
    free(v8NpObject);
}

static PassOwnArrayPtr<v8::Handle<v8::Value> > createValueListFromVariantArgs(const NPVariant* arguments, uint32_t argumentCount, NPObject* owner)
{
    OwnArrayPtr<v8::Handle<v8::Value> > argv = adoptArrayPtr(new v8::Handle<v8::Value>[argumentCount]);
    for (uint32_t index = 0; index < argumentCount; index++) {
        const NPVariant* arg = &arguments[index];
        argv[index] = convertNPVariantToV8Object(arg, owner);
    }
    return argv.release();
}

// Create an identifier (null terminated utf8 char*) from the NPIdentifier.
static v8::Local<v8::String> npIdentifierToV8Identifier(NPIdentifier name)
{
    PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(name);
    if (identifier->isString)
        return v8::String::New(static_cast<const char*>(identifier->value.string));

    char buffer[32];
    snprintf(buffer, sizeof(buffer), "%d", identifier->value.number);
    return v8::String::New(buffer);
}

NPObject* v8ObjectToNPObject(v8::Handle<v8::Object> object)
{
    return reinterpret_cast<NPObject*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); 
}

static NPClass V8NPObjectClass = { NP_CLASS_STRUCT_VERSION,
                                   allocV8NPObject,
                                   freeV8NPObject,
                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

// NPAPI's npruntime functions.
NPClass* npScriptObjectClass = &V8NPObjectClass;

NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, DOMWindow* root)
{
    // Check to see if this object is already wrapped.
    if (object->InternalFieldCount() == npObjectInternalFieldCount) {
        WrapperTypeInfo* typeInfo = static_cast<WrapperTypeInfo*>(object->GetPointerFromInternalField(v8DOMWrapperTypeIndex));
        if (typeInfo == npObjectTypeInfo()) {

            NPObject* returnValue = v8ObjectToNPObject(object);
            _NPN_RetainObject(returnValue);
            return returnValue;
        }
    }

    int v8ObjectHash = object->GetIdentityHash();
    ASSERT(v8ObjectHash);
    V8NPObjectMap::iterator iter = staticV8NPObjectMap()->find(v8ObjectHash);
    if (iter != staticV8NPObjectMap()->end()) {
        V8NPObjectVector& objects = iter->second;
        for (size_t index = 0; index < objects.size(); ++index) {
            V8NPObject* v8npObject = objects.at(index);
            if (v8npObject->rootObject == root) {
                ASSERT(v8npObject->v8Object == object);
                _NPN_RetainObject(&v8npObject->object);
                return reinterpret_cast<NPObject*>(v8npObject);
            }
        }
    } else {
        iter = staticV8NPObjectMap()->set(v8ObjectHash, V8NPObjectVector()).iterator;
    }

    V8NPObject* v8npObject = reinterpret_cast<V8NPObject*>(_NPN_CreateObject(npp, &V8NPObjectClass));
    v8npObject->v8Object = v8::Persistent<v8::Object>::New(object);
#ifndef NDEBUG
    V8GCController::registerGlobalHandle(NPOBJECT, v8npObject, v8npObject->v8Object);
#endif
    v8npObject->rootObject = root;

    iter->second.append(v8npObject);

    return reinterpret_cast<NPObject*>(v8npObject);
}

} // namespace WebCore

bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
    if (!npObject)
        return false;

    if (npObject->_class != npScriptObjectClass) {
        if (npObject->_class->invoke)
            return npObject->_class->invoke(npObject, methodName, arguments, argumentCount, result);

        VOID_TO_NPVARIANT(*result);
        return true;
    }

    V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject);

    PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(methodName);
    if (!identifier->isString)
        return false;

    if (!strcmp(identifier->value.string, "eval")) {
        if (argumentCount != 1)
            return false;
        if (arguments[0].type != NPVariantType_String)
            return false;
        return _NPN_Evaluate(npp, npObject, const_cast<NPString*>(&arguments[0].value.stringValue), result);
    }

    v8::HandleScope handleScope;
    // FIXME: should use the plugin's owner frame as the security context.
    v8::Handle<v8::Context> context = toV8Context(npp, npObject);
    if (context.IsEmpty())
        return false;

    v8::Context::Scope scope(context);
    ExceptionCatcher exceptionCatcher;

    v8::Handle<v8::Value> functionObject = v8NpObject->v8Object->Get(v8::String::New(identifier->value.string));
    if (functionObject.IsEmpty() || functionObject->IsNull()) {
        NULL_TO_NPVARIANT(*result);
        return false;
    }
    if (functionObject->IsUndefined()) {
        VOID_TO_NPVARIANT(*result);
        return false;
    }

    Frame* frame = v8NpObject->rootObject->frame();
    ASSERT(frame);

    // Call the function object.
    v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(functionObject);
    OwnArrayPtr<v8::Handle<v8::Value> > argv = createValueListFromVariantArgs(arguments, argumentCount, npObject);
    v8::Local<v8::Value> resultObject = frame->script()->callFunction(function, v8NpObject->v8Object, argumentCount, argv.get());

    // If we had an error, return false.  The spec is a little unclear here, but says "Returns true if the method was
    // successfully invoked".  If we get an error return value, was that successfully invoked?
    if (resultObject.IsEmpty())
        return false;

    convertV8ObjectToNPVariant(resultObject, npObject, result);
    return true;
}

// FIXME: Fix it same as _NPN_Invoke (HandleScope and such).
bool _NPN_InvokeDefault(NPP npp, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
    if (!npObject)
        return false;

    if (npObject->_class != npScriptObjectClass) {
        if (npObject->_class->invokeDefault)
            return npObject->_class->invokeDefault(npObject, arguments, argumentCount, result);

        VOID_TO_NPVARIANT(*result);
        return true;
    }

    V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject);

    VOID_TO_NPVARIANT(*result);

    v8::HandleScope handleScope;
    v8::Handle<v8::Context> context = toV8Context(npp, npObject);
    if (context.IsEmpty())
        return false;

    v8::Context::Scope scope(context);
    ExceptionCatcher exceptionCatcher;

    // Lookup the function object and call it.
    v8::Handle<v8::Object> functionObject(v8NpObject->v8Object);
    if (!functionObject->IsFunction())
        return false;

    v8::Local<v8::Value> resultObject;
    v8::Handle<v8::Function> function(v8::Function::Cast(*functionObject));
    if (!function->IsNull()) {
        Frame* frame = v8NpObject->rootObject->frame();
        ASSERT(frame);

        OwnArrayPtr<v8::Handle<v8::Value> > argv = createValueListFromVariantArgs(arguments, argumentCount, npObject);
        resultObject = frame->script()->callFunction(function, functionObject, argumentCount, argv.get());
    }
    // If we had an error, return false.  The spec is a little unclear here, but says "Returns true if the method was
    // successfully invoked".  If we get an error return value, was that successfully invoked?
    if (resultObject.IsEmpty())
        return false;

    convertV8ObjectToNPVariant(resultObject, npObject, result);
    return true;
}

bool _NPN_Evaluate(NPP npp, NPObject* npObject, NPString* npScript, NPVariant* result)
{
    bool popupsAllowed = PlatformSupport::popupsAllowed(npp);
    return _NPN_EvaluateHelper(npp, popupsAllowed, npObject, npScript, result);
}

bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPString* npScript, NPVariant* result)
{
    VOID_TO_NPVARIANT(*result);
    if (!npObject)
        return false;

    if (npObject->_class != npScriptObjectClass) {
        // Check if the object passed in is wrapped. If yes, then we need to invoke on the underlying object.
        NPObject* actualObject = NPObjectWrapper::getUnderlyingNPObject(npObject);
        if (!actualObject)
            return false;
        npObject = actualObject;
    }

    v8::HandleScope handleScope;
    v8::Handle<v8::Context> context = toV8Context(npp, npObject);
    if (context.IsEmpty())
        return false;

    v8::Context::Scope scope(context);
    ExceptionCatcher exceptionCatcher;

    // FIXME: Is this branch still needed after switching to using UserGestureIndicator?
    String filename;
    if (!popupsAllowed)
        filename = "npscript";

    V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject);
    Frame* frame = v8NpObject->rootObject->frame();
    ASSERT(frame);

    String script = String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length);

    UserGestureIndicator gestureIndicator(popupsAllowed ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture);
    v8::Local<v8::Value> v8result = frame->script()->compileAndRunScript(ScriptSourceCode(script, KURL(ParsedURLString, filename)));

    if (v8result.IsEmpty())
        return false;

    if (_NPN_IsAlive(npObject))
        convertV8ObjectToNPVariant(v8result, npObject, result);
    return true;
}

bool _NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NPVariant* result)
{
    if (!npObject)
        return false;

    if (npObject->_class == npScriptObjectClass) {
        V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject);

        v8::HandleScope handleScope;
        v8::Handle<v8::Context> context = toV8Context(npp, npObject);
        if (context.IsEmpty())
            return false;

        v8::Context::Scope scope(context);
        ExceptionCatcher exceptionCatcher;

        v8::Handle<v8::Object> obj(object->v8Object);
        v8::Local<v8::Value> v8result = obj->Get(npIdentifierToV8Identifier(propertyName));
        
        if (v8result.IsEmpty())
            return false;

        convertV8ObjectToNPVariant(v8result, npObject, result);
        return true;
    }

    if (npObject->_class->hasProperty && npObject->_class->getProperty) {
        if (npObject->_class->hasProperty(npObject, propertyName))
            return npObject->_class->getProperty(npObject, propertyName, result);
    }

    VOID_TO_NPVARIANT(*result);
    return false;
}

bool _NPN_SetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, const NPVariant* value)
{
    if (!npObject)
        return false;

    if (npObject->_class == npScriptObjectClass) {
        V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject);

        v8::HandleScope handleScope;
        v8::Handle<v8::Context> context = toV8Context(npp, npObject);
        if (context.IsEmpty())
            return false;

        v8::Context::Scope scope(context);
        ExceptionCatcher exceptionCatcher;

        v8::Handle<v8::Object> obj(object->v8Object);
        obj->Set(npIdentifierToV8Identifier(propertyName),
                 convertNPVariantToV8Object(value, object->rootObject->frame()->script()->windowScriptNPObject()));
        return true;
    }

    if (npObject->_class->setProperty)
        return npObject->_class->setProperty(npObject, propertyName, value);

    return false;
}

bool _NPN_RemoveProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName)
{
    if (!npObject)
        return false;
    if (npObject->_class != npScriptObjectClass)
        return false;

    V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject);

    v8::HandleScope handleScope;
    v8::Handle<v8::Context> context = toV8Context(npp, npObject);
    if (context.IsEmpty())
        return false;
    v8::Context::Scope scope(context);
    ExceptionCatcher exceptionCatcher;

    v8::Handle<v8::Object> obj(object->v8Object);
    // FIXME: Verify that setting to undefined is right.
    obj->Set(npIdentifierToV8Identifier(propertyName), v8::Undefined());
    return true;
}

bool _NPN_HasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName)
{
    if (!npObject)
        return false;

    if (npObject->_class == npScriptObjectClass) {
        V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject);

        v8::HandleScope handleScope;
        v8::Handle<v8::Context> context = toV8Context(npp, npObject);
        if (context.IsEmpty())
            return false;
        v8::Context::Scope scope(context);
        ExceptionCatcher exceptionCatcher;

        v8::Handle<v8::Object> obj(object->v8Object);
        return obj->Has(npIdentifierToV8Identifier(propertyName));
    }

    if (npObject->_class->hasProperty)
        return npObject->_class->hasProperty(npObject, propertyName);
    return false;
}

bool _NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName)
{
    if (!npObject)
        return false;

    if (npObject->_class == npScriptObjectClass) {
        V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject);

        v8::HandleScope handleScope;
        v8::Handle<v8::Context> context = toV8Context(npp, npObject);
        if (context.IsEmpty())
            return false;
        v8::Context::Scope scope(context);
        ExceptionCatcher exceptionCatcher;

        v8::Handle<v8::Object> obj(object->v8Object);
        v8::Handle<v8::Value> prop = obj->Get(npIdentifierToV8Identifier(methodName));
        return prop->IsFunction();
    }

    if (npObject->_class->hasMethod)
        return npObject->_class->hasMethod(npObject, methodName);
    return false;
}

void _NPN_SetException(NPObject* npObject, const NPUTF8 *message)
{
    if (!npObject || npObject->_class != npScriptObjectClass) {
        // We won't be able to find a proper scope for this exception, so just throw it.
        // This is consistent with JSC, which throws a global exception all the time.
        throwError(GeneralError, message);
        return;
    }
    v8::HandleScope handleScope;
    v8::Handle<v8::Context> context = toV8Context(0, npObject);
    if (context.IsEmpty())
        return;

    v8::Context::Scope scope(context);
    ExceptionCatcher exceptionCatcher;

    throwError(GeneralError, message);
}

bool _NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifier, uint32_t* count)
{
    if (!npObject)
        return false;

    if (npObject->_class == npScriptObjectClass) {
        V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject);

        v8::HandleScope handleScope;
        v8::Handle<v8::Context> context = toV8Context(npp, npObject);
        if (context.IsEmpty())
            return false;
        v8::Context::Scope scope(context);
        ExceptionCatcher exceptionCatcher;

        v8::Handle<v8::Object> obj(object->v8Object);

        // FIXME: http://b/issue?id=1210340: Use a v8::Object::Keys() method when it exists, instead of evaluating javascript.

        // FIXME: Figure out how to cache this helper function.  Run a helper function that collects the properties
        // on the object into an array.
        const char enumeratorCode[] =
            "(function (obj) {"
            "  var props = [];"
            "  for (var prop in obj) {"
            "    props[props.length] = prop;"
            "  }"
            "  return props;"
            "});";
        v8::Handle<v8::String> source = v8::String::New(enumeratorCode);
        v8::Handle<v8::Script> script = v8::Script::Compile(source, 0);
        v8::Handle<v8::Value> enumeratorObj = script->Run();
        v8::Handle<v8::Function> enumerator = v8::Handle<v8::Function>::Cast(enumeratorObj);
        v8::Handle<v8::Value> argv[] = { obj };
        v8::Local<v8::Value> propsObj = enumerator->Call(v8::Handle<v8::Object>::Cast(enumeratorObj), ARRAYSIZE_UNSAFE(argv), argv);
        if (propsObj.IsEmpty())
            return false;

        // Convert the results into an array of NPIdentifiers.
        v8::Handle<v8::Array> props = v8::Handle<v8::Array>::Cast(propsObj);
        *count = props->Length();
        *identifier = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier*) * *count));
        for (uint32_t i = 0; i < *count; ++i) {
            v8::Local<v8::Value> name = props->Get(v8Integer(i));
            (*identifier)[i] = getStringIdentifier(v8::Local<v8::String>::Cast(name));
        }
        return true;
    }

    if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(npObject->_class) && npObject->_class->enumerate)
       return npObject->_class->enumerate(npObject, identifier, count);

    return false;
}

bool _NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
    if (!npObject)
        return false;

    if (npObject->_class == npScriptObjectClass) {
        V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject);

        v8::HandleScope handleScope;
        v8::Handle<v8::Context> context = toV8Context(npp, npObject);
        if (context.IsEmpty())
            return false;
        v8::Context::Scope scope(context);
        ExceptionCatcher exceptionCatcher;

        // Lookup the constructor function.
        v8::Handle<v8::Object> ctorObj(object->v8Object);
        if (!ctorObj->IsFunction())
            return false;

        // Call the constructor.
        v8::Local<v8::Value> resultObject;
        v8::Handle<v8::Function> ctor(v8::Function::Cast(*ctorObj));
        if (!ctor->IsNull()) {
            Frame* frame = object->rootObject->frame();
            ASSERT(frame);
            OwnArrayPtr<v8::Handle<v8::Value> > argv = createValueListFromVariantArgs(arguments, argumentCount, npObject);
            resultObject = V8ObjectConstructor::newInstanceInDocument(ctor, argumentCount, argv.get(), frame ? frame->document() : 0);
        }

        if (resultObject.IsEmpty())
            return false;

        convertV8ObjectToNPVariant(resultObject, npObject, result);
        return true;
    }

    if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(npObject->_class) && npObject->_class->construct)
        return npObject->_class->construct(npObject, arguments, argumentCount, result);

    return false;
}
