/*
 * Copyright (C) 2018 Igalia S.L.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include "JSCWrapperMap.h"

#include "APICast.h"
#include "IntegrityInlines.h"
#include "JSAPIWrapperGlobalObject.h"
#include "JSAPIWrapperObject.h"
#include "JSCClassPrivate.h"
#include "JSCContextPrivate.h"
#include "JSCGLibWrapperObject.h"
#include "JSCInlines.h"
#include "JSCValuePrivate.h"
#include "JSCallbackObject.h"
#include "JSContextRef.h"

namespace JSC {

WrapperMap::WrapperMap(JSGlobalContextRef jsContext)
    : m_cachedJSWrappers(makeUnique<JSC::WeakGCMap<gpointer, JSC::JSObject>>(toJS(jsContext)->vm()))
{
}

WrapperMap::~WrapperMap()
{
    for (const auto& jscClass : m_classMap.values())
        jscClassInvalidate(jscClass.get());
}

GRefPtr<JSCValue> WrapperMap::gobjectWrapper(JSCContext* jscContext, JSValueRef jsValue)
{
    auto* jsContext = jscContextGetJSContext(jscContext);
    JSC::JSLockHolder locker(toJS(jsContext));
    ASSERT(toJSGlobalObject(jsContext)->wrapperMap() == this);
    GRefPtr<JSCValue> value = m_cachedGObjectWrappers.get(jsValue);
    if (!value) {
        value = adoptGRef(jscValueCreate(jscContext, jsValue));
        m_cachedGObjectWrappers.set(jsValue, value.get());
    }
    return value;
}

void WrapperMap::unwrap(JSValueRef jsValue)
{
    ASSERT(m_cachedGObjectWrappers.contains(jsValue));
    m_cachedGObjectWrappers.remove(jsValue);
}

void WrapperMap::registerClass(JSCClass* jscClass)
{
    auto* jsClass = jscClassGetJSClass(jscClass);
    ASSERT(!m_classMap.contains(jsClass));
    m_classMap.set(jsClass, jscClass);
}

JSCClass* WrapperMap::registeredClass(JSClassRef jsClass) const
{
    return m_classMap.get(jsClass);
}

JSObject* WrapperMap::createJSWrapper(JSGlobalContextRef jsContext, JSClassRef jsClass, JSValueRef prototype, gpointer wrappedObject, GDestroyNotify destroyFunction)
{
    ASSERT(toJSGlobalObject(jsContext)->wrapperMap() == this);
    JSGlobalObject* globalObject = toJS(jsContext);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto* object = JSC::JSCallbackObject<JSC::JSAPIWrapperObject>::create(globalObject, globalObject->glibWrapperObjectStructure(), jsClass, nullptr);
    if (wrappedObject) {
        object->setWrappedObject(new JSC::JSCGLibWrapperObject(wrappedObject, destroyFunction));
        m_cachedJSWrappers->set(wrappedObject, object);
    }
    if (prototype)
        JSObjectSetPrototype(jsContext, toRef(object), prototype);
    else if (auto* jsPrototype = jsClass->prototype(globalObject))
        object->setPrototypeDirect(vm, jsPrototype);
    return object;
}

JSGlobalContextRef WrapperMap::createContextWithJSWrapper(JSContextGroupRef jsGroup, JSClassRef jsClass, JSValueRef prototype, gpointer wrappedObject, GDestroyNotify destroyFunction)
{
    Ref<VM> vm(*toJS(jsGroup));
    JSLockHolder locker(vm.ptr());
    auto* globalObject = JSCallbackObject<JSAPIWrapperGlobalObject>::create(vm.get(), jsClass, JSCallbackObject<JSAPIWrapperGlobalObject>::createStructure(vm.get(), nullptr, jsNull()));
    if (wrappedObject) {
        globalObject->setWrappedObject(new JSC::JSCGLibWrapperObject(wrappedObject, destroyFunction));
        m_cachedJSWrappers->set(wrappedObject, globalObject);
    }
    if (prototype)
        globalObject->resetPrototype(vm.get(), toJS(globalObject, prototype));
    else if (auto jsPrototype = jsClass->prototype(globalObject))
        globalObject->resetPrototype(vm.get(), jsPrototype);
    else
        globalObject->resetPrototype(vm.get(), jsNull());

    return JSGlobalContextRetain(toGlobalRef(globalObject));
}

JSObject* WrapperMap::jsWrapper(gpointer wrappedObject) const
{
    if (!wrappedObject)
        return nullptr;
    return m_cachedJSWrappers->get(wrappedObject);
}

gpointer WrapperMap::wrappedObject(JSGlobalContextRef jsContext, JSObjectRef jsObject) const
{
    ASSERT(toJSGlobalObject(jsContext)->wrapperMap() == this);
    JSLockHolder locker(toJS(jsContext));
    auto* object = toJS(jsObject);
    if (object->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>>()) {
        if (auto* wrapper = JSC::jsCast<JSC::JSAPIWrapperObject*>(object)->wrappedObject())
            return static_cast<JSC::JSCGLibWrapperObject*>(wrapper)->object();
    }
    if (object->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperGlobalObject>>()) {
        if (auto* wrapper = JSC::jsCast<JSC::JSAPIWrapperGlobalObject*>(object)->wrappedObject())
            return wrapper->object();
    }
    return nullptr;
}

} // namespace JSC
