/*
    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(WEBGL)

#include "JSWebGLContextAttributes.h"

#include "JSDOMConvertBoolean.h"
#include "JSDOMConvertOptional.h"
#include "JSDOMGlobalObject.h"
#include "ScriptExecutionContext.h"
#include <JavaScriptCore/JSCInlines.h>
#include <JavaScriptCore/JSString.h>
#include <JavaScriptCore/ObjectConstructor.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/SortedArrayMap.h>


namespace WebCore {
using namespace JSC;

#if ENABLE(WEBGL)

template<> ConversionResult<IDLDictionary<WebGLContextAttributes>> convertDictionary<WebGLContextAttributes>(JSGlobalObject& lexicalGlobalObject, JSValue value)
{
    auto& vm = JSC::getVM(&lexicalGlobalObject);
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    bool isNullOrUndefined = value.isUndefinedOrNull();
    auto* object = isNullOrUndefined ? nullptr : value.getObject();
    if (UNLIKELY(!isNullOrUndefined && !object)) {
        throwTypeError(&lexicalGlobalObject, throwScope);
        return ConversionResultException { };
    }
    WebGLContextAttributes result;
    JSValue alphaValue;
    if (isNullOrUndefined)
        alphaValue = jsUndefined();
    else {
        alphaValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "alpha"_s));
        RETURN_IF_EXCEPTION(throwScope, ConversionResultException { });
    }
    auto alphaConversionResult = convertOptionalWithDefault<IDLBoolean>(lexicalGlobalObject, alphaValue, [&]() -> ConversionResult<IDLBoolean> { return Converter<IDLBoolean>::ReturnType { true }; });
    if (UNLIKELY(alphaConversionResult.hasException(throwScope)))
        return ConversionResultException { };
    result.alpha = alphaConversionResult.releaseReturnValue();
    JSValue antialiasValue;
    if (isNullOrUndefined)
        antialiasValue = jsUndefined();
    else {
        antialiasValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "antialias"_s));
        RETURN_IF_EXCEPTION(throwScope, ConversionResultException { });
    }
    auto antialiasConversionResult = convertOptionalWithDefault<IDLBoolean>(lexicalGlobalObject, antialiasValue, [&]() -> ConversionResult<IDLBoolean> { return Converter<IDLBoolean>::ReturnType { true }; });
    if (UNLIKELY(antialiasConversionResult.hasException(throwScope)))
        return ConversionResultException { };
    result.antialias = antialiasConversionResult.releaseReturnValue();
    JSValue depthValue;
    if (isNullOrUndefined)
        depthValue = jsUndefined();
    else {
        depthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "depth"_s));
        RETURN_IF_EXCEPTION(throwScope, ConversionResultException { });
    }
    auto depthConversionResult = convertOptionalWithDefault<IDLBoolean>(lexicalGlobalObject, depthValue, [&]() -> ConversionResult<IDLBoolean> { return Converter<IDLBoolean>::ReturnType { true }; });
    if (UNLIKELY(depthConversionResult.hasException(throwScope)))
        return ConversionResultException { };
    result.depth = depthConversionResult.releaseReturnValue();
    if (jsCast<JSDOMGlobalObject*>(&lexicalGlobalObject)->scriptExecutionContext()->settingsValues().domTestingAPIsEnabled) {
        JSValue failContextCreationForTestingValue;
        if (isNullOrUndefined)
            failContextCreationForTestingValue = jsUndefined();
        else {
            failContextCreationForTestingValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "failContextCreationForTesting"_s));
            RETURN_IF_EXCEPTION(throwScope, ConversionResultException { });
        }
        auto failContextCreationForTestingConversionResult = convertOptionalWithDefault<IDLEnumeration<WebGLContextAttributes::SimulatedCreationFailure>>(lexicalGlobalObject, failContextCreationForTestingValue, [&]() -> ConversionResult<IDLEnumeration<WebGLContextAttributes::SimulatedCreationFailure>> { return Converter<IDLEnumeration<WebGLContextAttributes::SimulatedCreationFailure>>::ReturnType { WebGLContextAttributes::SimulatedCreationFailure::None }; });
        if (UNLIKELY(failContextCreationForTestingConversionResult.hasException(throwScope)))
            return ConversionResultException { };
        result.failContextCreationForTesting = failContextCreationForTestingConversionResult.releaseReturnValue();
    }
    JSValue failIfMajorPerformanceCaveatValue;
    if (isNullOrUndefined)
        failIfMajorPerformanceCaveatValue = jsUndefined();
    else {
        failIfMajorPerformanceCaveatValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "failIfMajorPerformanceCaveat"_s));
        RETURN_IF_EXCEPTION(throwScope, ConversionResultException { });
    }
    auto failIfMajorPerformanceCaveatConversionResult = convertOptionalWithDefault<IDLBoolean>(lexicalGlobalObject, failIfMajorPerformanceCaveatValue, [&]() -> ConversionResult<IDLBoolean> { return Converter<IDLBoolean>::ReturnType { false }; });
    if (UNLIKELY(failIfMajorPerformanceCaveatConversionResult.hasException(throwScope)))
        return ConversionResultException { };
    result.failIfMajorPerformanceCaveat = failIfMajorPerformanceCaveatConversionResult.releaseReturnValue();
    JSValue powerPreferenceValue;
    if (isNullOrUndefined)
        powerPreferenceValue = jsUndefined();
    else {
        powerPreferenceValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "powerPreference"_s));
        RETURN_IF_EXCEPTION(throwScope, ConversionResultException { });
    }
    auto powerPreferenceConversionResult = convertOptionalWithDefault<IDLEnumeration<WebGLContextAttributes::PowerPreference>>(lexicalGlobalObject, powerPreferenceValue, [&]() -> ConversionResult<IDLEnumeration<WebGLContextAttributes::PowerPreference>> { return Converter<IDLEnumeration<WebGLContextAttributes::PowerPreference>>::ReturnType { WebGLContextAttributes::PowerPreference::Default }; });
    if (UNLIKELY(powerPreferenceConversionResult.hasException(throwScope)))
        return ConversionResultException { };
    result.powerPreference = powerPreferenceConversionResult.releaseReturnValue();
    JSValue premultipliedAlphaValue;
    if (isNullOrUndefined)
        premultipliedAlphaValue = jsUndefined();
    else {
        premultipliedAlphaValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "premultipliedAlpha"_s));
        RETURN_IF_EXCEPTION(throwScope, ConversionResultException { });
    }
    auto premultipliedAlphaConversionResult = convertOptionalWithDefault<IDLBoolean>(lexicalGlobalObject, premultipliedAlphaValue, [&]() -> ConversionResult<IDLBoolean> { return Converter<IDLBoolean>::ReturnType { true }; });
    if (UNLIKELY(premultipliedAlphaConversionResult.hasException(throwScope)))
        return ConversionResultException { };
    result.premultipliedAlpha = premultipliedAlphaConversionResult.releaseReturnValue();
    JSValue preserveDrawingBufferValue;
    if (isNullOrUndefined)
        preserveDrawingBufferValue = jsUndefined();
    else {
        preserveDrawingBufferValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "preserveDrawingBuffer"_s));
        RETURN_IF_EXCEPTION(throwScope, ConversionResultException { });
    }
    auto preserveDrawingBufferConversionResult = convertOptionalWithDefault<IDLBoolean>(lexicalGlobalObject, preserveDrawingBufferValue, [&]() -> ConversionResult<IDLBoolean> { return Converter<IDLBoolean>::ReturnType { false }; });
    if (UNLIKELY(preserveDrawingBufferConversionResult.hasException(throwScope)))
        return ConversionResultException { };
    result.preserveDrawingBuffer = preserveDrawingBufferConversionResult.releaseReturnValue();
    JSValue stencilValue;
    if (isNullOrUndefined)
        stencilValue = jsUndefined();
    else {
        stencilValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "stencil"_s));
        RETURN_IF_EXCEPTION(throwScope, ConversionResultException { });
    }
    auto stencilConversionResult = convertOptionalWithDefault<IDLBoolean>(lexicalGlobalObject, stencilValue, [&]() -> ConversionResult<IDLBoolean> { return Converter<IDLBoolean>::ReturnType { false }; });
    if (UNLIKELY(stencilConversionResult.hasException(throwScope)))
        return ConversionResultException { };
    result.stencil = stencilConversionResult.releaseReturnValue();
#if ENABLE(WEBXR)
    if (jsCast<JSDOMGlobalObject*>(&lexicalGlobalObject)->scriptExecutionContext()->settingsValues().webXREnabled) {
        JSValue xrCompatibleValue;
        if (isNullOrUndefined)
            xrCompatibleValue = jsUndefined();
        else {
            xrCompatibleValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "xrCompatible"_s));
            RETURN_IF_EXCEPTION(throwScope, ConversionResultException { });
        }
        auto xrCompatibleConversionResult = convertOptionalWithDefault<IDLBoolean>(lexicalGlobalObject, xrCompatibleValue, [&]() -> ConversionResult<IDLBoolean> { return Converter<IDLBoolean>::ReturnType { false }; });
        if (UNLIKELY(xrCompatibleConversionResult.hasException(throwScope)))
            return ConversionResultException { };
        result.xrCompatible = xrCompatibleConversionResult.releaseReturnValue();
    }
#endif
    return result;
}

JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const WebGLContextAttributes& dictionary)
{
    auto& vm = JSC::getVM(&lexicalGlobalObject);
    auto throwScope = DECLARE_THROW_SCOPE(vm);

    auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype());

    auto alphaValue = toJS<IDLBoolean>(lexicalGlobalObject, throwScope, dictionary.alpha);
    RETURN_IF_EXCEPTION(throwScope, { });
    result->putDirect(vm, JSC::Identifier::fromString(vm, "alpha"_s), alphaValue);
    auto antialiasValue = toJS<IDLBoolean>(lexicalGlobalObject, throwScope, dictionary.antialias);
    RETURN_IF_EXCEPTION(throwScope, { });
    result->putDirect(vm, JSC::Identifier::fromString(vm, "antialias"_s), antialiasValue);
    auto depthValue = toJS<IDLBoolean>(lexicalGlobalObject, throwScope, dictionary.depth);
    RETURN_IF_EXCEPTION(throwScope, { });
    result->putDirect(vm, JSC::Identifier::fromString(vm, "depth"_s), depthValue);
    if (jsCast<JSDOMGlobalObject*>(&globalObject)->scriptExecutionContext()->settingsValues().domTestingAPIsEnabled) {
        auto failContextCreationForTestingValue = toJS<IDLEnumeration<WebGLContextAttributes::SimulatedCreationFailure>>(lexicalGlobalObject, throwScope, dictionary.failContextCreationForTesting);
        RETURN_IF_EXCEPTION(throwScope, { });
        result->putDirect(vm, JSC::Identifier::fromString(vm, "failContextCreationForTesting"_s), failContextCreationForTestingValue);
    }
    auto failIfMajorPerformanceCaveatValue = toJS<IDLBoolean>(lexicalGlobalObject, throwScope, dictionary.failIfMajorPerformanceCaveat);
    RETURN_IF_EXCEPTION(throwScope, { });
    result->putDirect(vm, JSC::Identifier::fromString(vm, "failIfMajorPerformanceCaveat"_s), failIfMajorPerformanceCaveatValue);
    auto powerPreferenceValue = toJS<IDLEnumeration<WebGLContextAttributes::PowerPreference>>(lexicalGlobalObject, throwScope, dictionary.powerPreference);
    RETURN_IF_EXCEPTION(throwScope, { });
    result->putDirect(vm, JSC::Identifier::fromString(vm, "powerPreference"_s), powerPreferenceValue);
    auto premultipliedAlphaValue = toJS<IDLBoolean>(lexicalGlobalObject, throwScope, dictionary.premultipliedAlpha);
    RETURN_IF_EXCEPTION(throwScope, { });
    result->putDirect(vm, JSC::Identifier::fromString(vm, "premultipliedAlpha"_s), premultipliedAlphaValue);
    auto preserveDrawingBufferValue = toJS<IDLBoolean>(lexicalGlobalObject, throwScope, dictionary.preserveDrawingBuffer);
    RETURN_IF_EXCEPTION(throwScope, { });
    result->putDirect(vm, JSC::Identifier::fromString(vm, "preserveDrawingBuffer"_s), preserveDrawingBufferValue);
    auto stencilValue = toJS<IDLBoolean>(lexicalGlobalObject, throwScope, dictionary.stencil);
    RETURN_IF_EXCEPTION(throwScope, { });
    result->putDirect(vm, JSC::Identifier::fromString(vm, "stencil"_s), stencilValue);
#if ENABLE(WEBXR)
    if (jsCast<JSDOMGlobalObject*>(&globalObject)->scriptExecutionContext()->settingsValues().webXREnabled) {
        auto xrCompatibleValue = toJS<IDLBoolean>(lexicalGlobalObject, throwScope, dictionary.xrCompatible);
        RETURN_IF_EXCEPTION(throwScope, { });
        result->putDirect(vm, JSC::Identifier::fromString(vm, "xrCompatible"_s), xrCompatibleValue);
    }
#endif
    return result;
}

#endif

String convertEnumerationToString(WebGLContextAttributes::PowerPreference enumerationValue)
{
    static const NeverDestroyed<String> values[] = {
        MAKE_STATIC_STRING_IMPL("default"),
        MAKE_STATIC_STRING_IMPL("low-power"),
        MAKE_STATIC_STRING_IMPL("high-performance"),
    };
    static_assert(static_cast<size_t>(WebGLContextAttributes::PowerPreference::Default) == 0, "WebGLContextAttributes::PowerPreference::Default is not 0 as expected");
    static_assert(static_cast<size_t>(WebGLContextAttributes::PowerPreference::LowPower) == 1, "WebGLContextAttributes::PowerPreference::LowPower is not 1 as expected");
    static_assert(static_cast<size_t>(WebGLContextAttributes::PowerPreference::HighPerformance) == 2, "WebGLContextAttributes::PowerPreference::HighPerformance is not 2 as expected");
    ASSERT(static_cast<size_t>(enumerationValue) < std::size(values));
    return values[static_cast<size_t>(enumerationValue)];
}

template<> JSString* convertEnumerationToJS(VM& vm, WebGLContextAttributes::PowerPreference enumerationValue)
{
    return jsStringWithCache(vm, convertEnumerationToString(enumerationValue));
}

template<> std::optional<WebGLContextAttributes::PowerPreference> parseEnumerationFromString<WebGLContextAttributes::PowerPreference>(const String& stringValue)
{
    static constexpr std::pair<ComparableASCIILiteral, WebGLContextAttributes::PowerPreference> mappings[] = {
        { "default", WebGLContextAttributes::PowerPreference::Default },
        { "high-performance", WebGLContextAttributes::PowerPreference::HighPerformance },
        { "low-power", WebGLContextAttributes::PowerPreference::LowPower },
    };
    static constexpr SortedArrayMap enumerationMapping { mappings };
    if (auto* enumerationValue = enumerationMapping.tryGet(stringValue); LIKELY(enumerationValue))
        return *enumerationValue;
    return std::nullopt;
}

template<> std::optional<WebGLContextAttributes::PowerPreference> parseEnumeration<WebGLContextAttributes::PowerPreference>(JSGlobalObject& lexicalGlobalObject, JSValue value)
{
    return parseEnumerationFromString<WebGLContextAttributes::PowerPreference>(value.toWTFString(&lexicalGlobalObject));
}

template<> ASCIILiteral expectedEnumerationValues<WebGLContextAttributes::PowerPreference>()
{
    return "\"default\", \"low-power\", \"high-performance\""_s;
}

#if ENABLE(WEBGL)

String convertEnumerationToString(WebGLContextAttributes::SimulatedCreationFailure enumerationValue)
{
    static const NeverDestroyed<String> values[] = {
        MAKE_STATIC_STRING_IMPL("None"),
        MAKE_STATIC_STRING_IMPL("IPCBufferOOM"),
        MAKE_STATIC_STRING_IMPL("CreationTimeout"),
        MAKE_STATIC_STRING_IMPL("FailPlatformContextCreation"),
    };
    static_assert(static_cast<size_t>(WebGLContextAttributes::SimulatedCreationFailure::None) == 0, "WebGLContextAttributes::SimulatedCreationFailure::None is not 0 as expected");
    static_assert(static_cast<size_t>(WebGLContextAttributes::SimulatedCreationFailure::IPCBufferOOM) == 1, "WebGLContextAttributes::SimulatedCreationFailure::IPCBufferOOM is not 1 as expected");
    static_assert(static_cast<size_t>(WebGLContextAttributes::SimulatedCreationFailure::CreationTimeout) == 2, "WebGLContextAttributes::SimulatedCreationFailure::CreationTimeout is not 2 as expected");
    static_assert(static_cast<size_t>(WebGLContextAttributes::SimulatedCreationFailure::FailPlatformContextCreation) == 3, "WebGLContextAttributes::SimulatedCreationFailure::FailPlatformContextCreation is not 3 as expected");
    ASSERT(static_cast<size_t>(enumerationValue) < std::size(values));
    return values[static_cast<size_t>(enumerationValue)];
}

template<> JSString* convertEnumerationToJS(VM& vm, WebGLContextAttributes::SimulatedCreationFailure enumerationValue)
{
    return jsStringWithCache(vm, convertEnumerationToString(enumerationValue));
}

template<> std::optional<WebGLContextAttributes::SimulatedCreationFailure> parseEnumerationFromString<WebGLContextAttributes::SimulatedCreationFailure>(const String& stringValue)
{
    static constexpr std::pair<ComparableASCIILiteral, WebGLContextAttributes::SimulatedCreationFailure> mappings[] = {
        { "CreationTimeout", WebGLContextAttributes::SimulatedCreationFailure::CreationTimeout },
        { "FailPlatformContextCreation", WebGLContextAttributes::SimulatedCreationFailure::FailPlatformContextCreation },
        { "IPCBufferOOM", WebGLContextAttributes::SimulatedCreationFailure::IPCBufferOOM },
        { "None", WebGLContextAttributes::SimulatedCreationFailure::None },
    };
    static constexpr SortedArrayMap enumerationMapping { mappings };
    if (auto* enumerationValue = enumerationMapping.tryGet(stringValue); LIKELY(enumerationValue))
        return *enumerationValue;
    return std::nullopt;
}

template<> std::optional<WebGLContextAttributes::SimulatedCreationFailure> parseEnumeration<WebGLContextAttributes::SimulatedCreationFailure>(JSGlobalObject& lexicalGlobalObject, JSValue value)
{
    return parseEnumerationFromString<WebGLContextAttributes::SimulatedCreationFailure>(value.toWTFString(&lexicalGlobalObject));
}

template<> ASCIILiteral expectedEnumerationValues<WebGLContextAttributes::SimulatedCreationFailure>()
{
    return "\"None\", \"IPCBufferOOM\", \"CreationTimeout\", \"FailPlatformContextCreation\""_s;
}

#endif

} // namespace WebCore

#endif // ENABLE(WEBGL)
