"use strict";
const testValue = Object.freeze({});

function assert(x, key) {
    if (!x)
        throw new Error(`Key: "${key}". Bad assertion!`);
}

function shouldThrow(func, errorMessage, key) {
    let errorThrown = false;
    try {
        func();
    } catch (error) {
        errorThrown = true;
        if (String(error) !== errorMessage)
            throw new Error(`Key: "${key}". Bad error: ${error}`);
    }
    if (!errorThrown)
        throw new Error(`Key: "${key}". Didn't throw!`);
}

function* testCases() {
    // hasSetterOrReadonlyProperties: false
    for (const key of ["isFinite", "eval", "globalThis", "parseInt", "EvalError", "JSON", "Uint8ClampedArray", "WeakMap"])
        yield [$vm.createGlobalObject(), key];
    for (const key of ["seal", "is", "values", "fromEntries", "defineProperty", "setPrototypeOf"])
        yield [$vm.createGlobalObject().Object, key];
    for (const key of ["apply", "construct", "has", "preventExtensions", "getPrototypeOf"])
        yield [$vm.createGlobalObject().Reflect, key];
    for (const key of ["toDateString", "toLocaleString", "getUTCMonth", "getDay", "setUTCMinutes", "setMonth"])
        yield [$vm.createGlobalObject().Date.prototype, key];
    for (const key of ["concat", "match", "padStart", "bold", "fixed", "small", "sub"])
        yield [$vm.createGlobalObject().String.prototype, key];

    // hasSetterOrReadonlyProperties: true
    for (const key of ["getUint16", "setInt8", "getFloat32", "setBigUint64"])
        yield [$vm.createGlobalObject().DataView.prototype, key];
    for (const key of ["toString", "valueOf"])
        yield [$vm.createGlobalObject().Symbol.prototype, key];
    for (const key of ["formatRange", "formatToParts", "resolvedOptions"])
        yield [$vm.createGlobalObject().Intl.DateTimeFormat.prototype, key];
    for (const key of ["formatToParts", "resolvedOptions"])
        yield [$vm.createGlobalObject().Intl.NumberFormat.prototype, key];
    for (const key of ["maximize", "minimize", "toString"])
        yield [$vm.createGlobalObject().Intl.Locale.prototype, key];

    yield [$vm.createStaticCustomValue(), "testStaticValueNoSetter"];
}

for (const [object, key] of testCases()) {
    object[key] = testValue;

    const desc = Object.getOwnPropertyDescriptor(object, key);
    assert(desc.value === testValue, key);
    assert(desc.writable, key);
    assert(!desc.enumerable, key);
    assert(desc.configurable, key);
}

for (const [object, key] of testCases()) {
    Object.preventExtensions(object);
    object[key] = testValue;

    const desc = Object.getOwnPropertyDescriptor(object, key);
    assert(desc.value === testValue, key);
    assert(desc.writable, key);
    assert(!desc.enumerable, key);
    assert(desc.configurable, key);
}

for (const [object, key] of testCases()) {
    Object.defineProperty(object, key, { enumerable: true, configurable: false });
    object[key] = testValue;

    const desc = Object.getOwnPropertyDescriptor(object, key);
    assert(desc.value === testValue, key);
    assert(desc.writable, key);
    assert(desc.enumerable, key);
    assert(!desc.configurable, key);
}

for (const [object, key] of testCases()) {
    Object.defineProperty(object, key, { writable: false });
    shouldThrow(() => { object[key] = testValue; }, "TypeError: Attempted to assign to readonly property.", key);

    const desc = Object.getOwnPropertyDescriptor(object, key);
    assert(desc.value !== testValue, key);
    assert(!desc.writable, key);
    assert(!desc.enumerable, key);
    assert(desc.configurable, key);
}

for (const [object, key] of testCases()) {
    const heir = Object.create(object);
    heir[key] = testValue;

    const desc = Object.getOwnPropertyDescriptor(heir, key);
    assert(desc.value === testValue, key);
    assert(desc.writable, key);
    assert(desc.enumerable, key);
    assert(desc.configurable, key);
    assert(object[key] !== testValue, key);
}

for (const [object, key] of testCases()) {
    const prototype = Object.getPrototypeOf(object);
    if (prototype !== null) {
        Object.defineProperty(prototype, key, {
            set() { throw new Error(`"${key}" setter should be unreachable!`); },
        });
    }

    const heir = Object.create(object);
    heir[key] = testValue;

    const desc = Object.getOwnPropertyDescriptor(heir, key);
    assert(desc.value === testValue, key);
    assert(desc.writable, key);
    assert(desc.enumerable, key);
    assert(desc.configurable, key);
    assert(object[key] !== testValue, key);
}

for (const [object, key] of testCases()) {
    const heir = Object.create(object);
    Object.preventExtensions(heir);

    shouldThrow(() => { heir[key] = testValue; }, "TypeError: Attempted to assign to readonly property.", key);
    assert(heir[key] !== testValue, key);
    assert(object[key] !== testValue, key);
}

for (const [object, key] of testCases()) {
    const target = {};
    assert(Reflect.set(target, key, testValue, object), key);
    assert(!target.hasOwnProperty(key), key);

    const desc = Object.getOwnPropertyDescriptor(object, key);
    assert(desc.value === testValue, key);
    assert(desc.writable, key);
    assert(!desc.enumerable, key);
    assert(desc.configurable, key);
}
