/*
    This file is part of the WebKit open source project.
    This file has been generated by generate-bindings.pl. DO NOT MODIFY!

    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"

#if ENABLE(MEDIA_SESSION)

#include "JSMediaSession.h"

#include "Dictionary.h"
#include "ExceptionCode.h"
#include "JSDOMBinding.h"
#include "JSDOMConstructor.h"
#include "JSDOMConvert.h"
#include "JSMediaRemoteControls.h"
#include <runtime/Error.h>
#include <runtime/FunctionPrototype.h>
#include <runtime/JSString.h>
#include <wtf/GetPtr.h>

using namespace JSC;

namespace WebCore {

template<typename T> Optional<T> parse(ExecState&, JSValue);
template<typename T> const char* expectedEnumerationValues();

JSString* jsStringWithCache(ExecState*, MediaSession::Kind);

JSString* jsStringWithCache(ExecState* state, MediaSession::Kind enumerationValue)
{
    static NeverDestroyed<const String> values[] = {
        ASCIILiteral("content"),
        ASCIILiteral("transient"),
        ASCIILiteral("transient-solo"),
        ASCIILiteral("ambient"),
    };
    static_assert(static_cast<size_t>(MediaSession::Kind::Content) == 0, "MediaSession::Kind::Content is not 0 as expected");
    static_assert(static_cast<size_t>(MediaSession::Kind::Transient) == 1, "MediaSession::Kind::Transient is not 1 as expected");
    static_assert(static_cast<size_t>(MediaSession::Kind::TransientSolo) == 2, "MediaSession::Kind::TransientSolo is not 2 as expected");
    static_assert(static_cast<size_t>(MediaSession::Kind::Ambient) == 3, "MediaSession::Kind::Ambient is not 3 as expected");
    ASSERT(static_cast<size_t>(enumerationValue) < WTF_ARRAY_LENGTH(values));
    return jsStringWithCache(state, values[static_cast<size_t>(enumerationValue)]);
}

template<> struct JSValueTraits<MediaSession::Kind> {
    static JSString* arrayJSValue(ExecState* state, JSDOMGlobalObject*, MediaSession::Kind value) { return jsStringWithCache(state, value); }
};

template<> Optional<MediaSession::Kind> parse<MediaSession::Kind>(ExecState& state, JSValue value)
{
    auto stringValue = value.toWTFString(&state);
    if (stringValue == "content")
        return MediaSession::Kind::Content;
    if (stringValue == "transient")
        return MediaSession::Kind::Transient;
    if (stringValue == "transient-solo")
        return MediaSession::Kind::TransientSolo;
    if (stringValue == "ambient")
        return MediaSession::Kind::Ambient;
    return Nullopt;
}

template<> MediaSession::Kind convert<MediaSession::Kind>(ExecState& state, JSValue value)
{
    VM& vm = state.vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    auto result = parse<MediaSession::Kind>(state, value);
    if (UNLIKELY(!result)) {
        throwTypeError(&state, throwScope);
        return { };
    }
    return result.value();
}

template<> inline const char* expectedEnumerationValues<MediaSession::Kind>()
{
    return "\"content\", \"transient\", \"transient-solo\", \"ambient\"";
}

// Functions

JSC::EncodedJSValue JSC_HOST_CALL jsMediaSessionPrototypeFunctionSetMetadata(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL jsMediaSessionPrototypeFunctionDeactivate(JSC::ExecState*);

// Attributes

JSC::EncodedJSValue jsMediaSessionKind(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
JSC::EncodedJSValue jsMediaSessionControls(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
JSC::EncodedJSValue jsMediaSessionConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSMediaSessionConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);

class JSMediaSessionPrototype : public JSC::JSNonFinalObject {
public:
    typedef JSC::JSNonFinalObject Base;
    static JSMediaSessionPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
    {
        JSMediaSessionPrototype* ptr = new (NotNull, JSC::allocateCell<JSMediaSessionPrototype>(vm.heap)) JSMediaSessionPrototype(vm, globalObject, structure);
        ptr->finishCreation(vm);
        return ptr;
    }

    DECLARE_INFO;
    static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
    {
        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
    }

private:
    JSMediaSessionPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure)
        : JSC::JSNonFinalObject(vm, structure)
    {
    }

    void finishCreation(JSC::VM&);
};

typedef JSDOMConstructor<JSMediaSession> JSMediaSessionConstructor;

template<> JSC::EncodedJSValue JSC_HOST_CALL JSMediaSessionConstructor::construct(JSC::ExecState* exec)
{
    ASSERT(exec);
    return constructJSMediaSession(*exec);
}

template<> JSValue JSMediaSessionConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject)
{
    UNUSED_PARAM(vm);
    return globalObject.functionPrototype();
}

template<> void JSMediaSessionConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject)
{
    putDirect(vm, vm.propertyNames->prototype, JSMediaSession::prototype(vm, &globalObject), DontDelete | ReadOnly | DontEnum);
    putDirect(vm, vm.propertyNames->name, jsNontrivialString(&vm, String(ASCIILiteral("MediaSession"))), ReadOnly | DontEnum);
    putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum);
}

template<> const ClassInfo JSMediaSessionConstructor::s_info = { "MediaSession", &Base::s_info, 0, CREATE_METHOD_TABLE(JSMediaSessionConstructor) };

/* Hash table for prototype */

static const HashTableValue JSMediaSessionPrototypeTableValues[] =
{
    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsMediaSessionConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSMediaSessionConstructor) } },
    { "kind", ReadOnly | CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsMediaSessionKind), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } },
    { "controls", ReadOnly | CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsMediaSessionControls), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } },
    { "setMetadata", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsMediaSessionPrototypeFunctionSetMetadata), (intptr_t) (1) } },
    { "deactivate", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsMediaSessionPrototypeFunctionDeactivate), (intptr_t) (0) } },
};

const ClassInfo JSMediaSessionPrototype::s_info = { "MediaSessionPrototype", &Base::s_info, 0, CREATE_METHOD_TABLE(JSMediaSessionPrototype) };

void JSMediaSessionPrototype::finishCreation(VM& vm)
{
    Base::finishCreation(vm);
    reifyStaticProperties(vm, JSMediaSessionPrototypeTableValues, *this);
}

const ClassInfo JSMediaSession::s_info = { "MediaSession", &Base::s_info, 0, CREATE_METHOD_TABLE(JSMediaSession) };

JSMediaSession::JSMediaSession(Structure* structure, JSDOMGlobalObject& globalObject, Ref<MediaSession>&& impl)
    : JSDOMWrapper<MediaSession>(structure, globalObject, WTFMove(impl))
{
}

JSObject* JSMediaSession::createPrototype(VM& vm, JSGlobalObject* globalObject)
{
    return JSMediaSessionPrototype::create(vm, globalObject, JSMediaSessionPrototype::createStructure(vm, globalObject, globalObject->objectPrototype()));
}

JSObject* JSMediaSession::prototype(VM& vm, JSGlobalObject* globalObject)
{
    return getDOMPrototype<JSMediaSession>(vm, globalObject);
}

void JSMediaSession::destroy(JSC::JSCell* cell)
{
    JSMediaSession* thisObject = static_cast<JSMediaSession*>(cell);
    thisObject->JSMediaSession::~JSMediaSession();
}

EncodedJSValue jsMediaSessionKind(ExecState* state, EncodedJSValue thisValue, PropertyName)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    UNUSED_PARAM(thisValue);
    JSValue decodedThisValue = JSValue::decode(thisValue);
    auto* castedThis = jsDynamicCast<JSMediaSession*>(decodedThisValue);
    if (UNLIKELY(!castedThis)) {
        return throwGetterTypeError(*state, throwScope, "MediaSession", "kind");
    }
    auto& impl = castedThis->wrapped();
    JSValue result = jsStringWithCache(state, impl.kind());
    return JSValue::encode(result);
}


EncodedJSValue jsMediaSessionControls(ExecState* state, EncodedJSValue thisValue, PropertyName)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    UNUSED_PARAM(thisValue);
    JSValue decodedThisValue = JSValue::decode(thisValue);
    auto* castedThis = jsDynamicCast<JSMediaSession*>(decodedThisValue);
    if (UNLIKELY(!castedThis)) {
        return throwGetterTypeError(*state, throwScope, "MediaSession", "controls");
    }
    auto& impl = castedThis->wrapped();
    JSValue result = toJS(state, castedThis->globalObject(), impl.controls());
    return JSValue::encode(result);
}


EncodedJSValue jsMediaSessionConstructor(ExecState* state, EncodedJSValue thisValue, PropertyName)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    JSMediaSessionPrototype* domObject = jsDynamicCast<JSMediaSessionPrototype*>(JSValue::decode(thisValue));
    if (UNLIKELY(!domObject))
        return throwVMTypeError(state, throwScope);
    return JSValue::encode(JSMediaSession::getConstructor(state->vm(), domObject->globalObject()));
}

bool setJSMediaSessionConstructor(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    JSValue value = JSValue::decode(encodedValue);
    JSMediaSessionPrototype* domObject = jsDynamicCast<JSMediaSessionPrototype*>(JSValue::decode(thisValue));
    if (UNLIKELY(!domObject)) {
        throwVMTypeError(state, throwScope);
        return false;
    }
    // Shadowing a built-in constructor
    return domObject->putDirect(state->vm(), state->propertyNames().constructor, value);
}

JSValue JSMediaSession::getConstructor(VM& vm, const JSGlobalObject* globalObject)
{
    return getDOMConstructor<JSMediaSessionConstructor>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject));
}

EncodedJSValue JSC_HOST_CALL jsMediaSessionPrototypeFunctionSetMetadata(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsDynamicCast<JSMediaSession*>(thisValue);
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "MediaSession", "setMetadata");
    ASSERT_GC_OBJECT_INHERITS(castedThis, JSMediaSession::info());
    auto& impl = castedThis->wrapped();
    if (UNLIKELY(state->argumentCount() < 1))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    auto metadata = Dictionary(state, state->uncheckedArgument(0));
    impl.setMetadata(WTFMove(metadata));
    return JSValue::encode(jsUndefined());
}

EncodedJSValue JSC_HOST_CALL jsMediaSessionPrototypeFunctionDeactivate(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsDynamicCast<JSMediaSession*>(thisValue);
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "MediaSession", "deactivate");
    ASSERT_GC_OBJECT_INHERITS(castedThis, JSMediaSession::info());
    auto& impl = castedThis->wrapped();
    impl.deactivate();
    return JSValue::encode(jsUndefined());
}

bool JSMediaSessionOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
{
    UNUSED_PARAM(handle);
    UNUSED_PARAM(visitor);
    return false;
}

void JSMediaSessionOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
{
    auto* jsMediaSession = jsCast<JSMediaSession*>(handle.slot()->asCell());
    auto& world = *static_cast<DOMWrapperWorld*>(context);
    uncacheWrapper(world, &jsMediaSession->wrapped(), jsMediaSession);
}

JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<MediaSession>&& impl)
{
#if COMPILER(CLANG)
    // If you hit this failure the interface definition has the ImplementationLacksVTable
    // attribute. You should remove that attribute. If the class has subclasses
    // that may be passed through this toJS() function you should use the SkipVTableValidation
    // attribute to MediaSession.
    static_assert(!__is_polymorphic(MediaSession), "MediaSession is polymorphic but the IDL claims it is not");
#endif
    return createWrapper<MediaSession>(globalObject, WTFMove(impl));
}

JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, MediaSession& impl)
{
    return wrap(state, globalObject, impl);
}

MediaSession* JSMediaSession::toWrapped(JSC::JSValue value)
{
    if (auto* wrapper = jsDynamicCast<JSMediaSession*>(value))
        return &wrapper->wrapped();
    return nullptr;
}

}

#endif // ENABLE(MEDIA_SESSION)
