import * as assert from '../assert.js';
import * as utilities from '../utilities.js';

const version = 0x01;
const emptyModuleArray = Uint8Array.of(0x0, 0x61, 0x73, 0x6d, version, 0x00, 0x00, 0x00);
const invalidConstructorInputs = [undefined, null, "", 1, {}, []];
const invalidInstanceImports = [null, "", 1];

const checkOwnPropertyDescriptor = (obj, prop, expect) => {
    const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
    assert.eq(typeof descriptor.value, expect.typeofvalue);
    assert.eq(descriptor.writable, expect.writable);
    assert.eq(descriptor.configurable, expect.configurable);
    assert.eq(descriptor.enumerable, expect.enumerable);
};

const checkAccessorOwnPropertyDescriptor = (obj, prop, expect) => {
    const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
    assert.eq(typeof descriptor.value, "undefined");
    assert.eq(typeof descriptor.writable, "undefined");
    assert.eq(descriptor.configurable, expect.configurable);
    assert.eq(descriptor.enumerable, expect.enumerable);
};

const functionProperties = {
    "validate": { length: 1 },
    "compile":  { length: 1 },
};
const constructorProperties = {
    "Module":       { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 },
    "Instance":     { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 },
    "Memory":       { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 },
    "Table":        { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 },
    "CompileError": { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 },
    "LinkError":    { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 },
    "RuntimeError": { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 },
};


assert.isNotUndef(WebAssembly);
checkOwnPropertyDescriptor(utilities.global, "WebAssembly", { typeofvalue: "object", writable: true, configurable: true, enumerable: false });
assert.eq(String(WebAssembly), "[object WebAssembly]");
assert.isUndef(WebAssembly.length);
assert.eq(WebAssembly instanceof Object, true);
assert.throws(() => WebAssembly(), TypeError, `WebAssembly is not a function. (In 'WebAssembly()', 'WebAssembly' is an instance of WebAssembly)`);
assert.throws(() => new WebAssembly(), TypeError, `WebAssembly is not a constructor (evaluating 'new WebAssembly()')`);

for (const f in functionProperties) {
    assert.isNotUndef(WebAssembly[f]);
    assert.eq(WebAssembly[f].name, f);
    assert.eq(WebAssembly[f].length, functionProperties[f].length);
}

for (const c in constructorProperties) {
    assert.isNotUndef(WebAssembly[c]);
    assert.eq(WebAssembly[c].name, c);
    assert.eq(WebAssembly[c].length, constructorProperties[c].length);
    checkOwnPropertyDescriptor(WebAssembly, c, constructorProperties[c]);
    checkOwnPropertyDescriptor(WebAssembly[c], "prototype", { typeofvalue: "object", writable: false, configurable: false, enumerable: false });
    if (["CompileError", "LinkError", "RuntimeError"].indexOf(c) >= 0)
        WebAssembly[c](); // Per spec, the WebAssembly.*Error types match ye olden JavaScript NativeError behavior: they can be constructed without `new`.
    else
        assert.throws(() => WebAssembly[c](), TypeError, `calling WebAssembly.${c} constructor without new is invalid`);
    switch (c) {
    case "Module":
        for (const invalid of invalidConstructorInputs)
            assert.throws(() => new WebAssembly[c](invalid), TypeError, `first argument must be an ArrayBufferView or an ArrayBuffer (evaluating 'new WebAssembly[c](invalid)')`);
        for (const buffer of [new ArrayBuffer(), new DataView(new ArrayBuffer()), new Int8Array(), new Uint8Array(), new Uint8ClampedArray(), new Int16Array(), new Uint16Array(), new Int32Array(), new Uint32Array(), new Float32Array(), new Float64Array()])
            // FIXME the following should be WebAssembly.CompileError. https://bugs.webkit.org/show_bug.cgi?id=163768
            assert.throws(() => new WebAssembly[c](buffer), Error, `WebAssembly.Module doesn't parse at byte 0: expected a module of at least 8 bytes (evaluating 'new WebAssembly[c](buffer)')`);
        assert.instanceof(new WebAssembly[c](emptyModuleArray), WebAssembly.Module);
        break;
    case "Instance":
        for (const invalid of invalidConstructorInputs)
            assert.throws(() => new WebAssembly[c](invalid), TypeError, `first argument to WebAssembly.Instance must be a WebAssembly.Module (evaluating 'new WebAssembly[c](invalid)')`);
        const instance = new WebAssembly[c](new WebAssembly.Module(emptyModuleArray));
        assert.instanceof(instance, WebAssembly.Instance);
        for (const invalid of invalidInstanceImports)
            assert.throws(() => new WebAssembly[c](new WebAssembly.Module(emptyModuleArray), invalid), TypeError, `second argument to WebAssembly.Instance must be undefined or an Object (evaluating 'new WebAssembly[c](new WebAssembly.Module(emptyModuleArray), invalid)')`);
        assert.isNotUndef(instance.exports);
        checkAccessorOwnPropertyDescriptor(WebAssembly.Instance.prototype, "exports", { configurable: true, enumerable: true });
        assert.throws(() => WebAssembly.Instance.prototype.exports = undefined, TypeError, `Attempted to assign to readonly property.`);
        assert.throws(() => WebAssembly.Instance.prototype.exports, TypeError, `expected |this| value to be an instance of WebAssembly.Instance`);
        assert.isUndef(instance.exports.__proto__);
        assert.eq(Reflect.isExtensible(instance.exports), false);
        assert.eq(Symbol.iterator in instance.exports, false);
        assert.eq(Symbol.toStringTag in instance.exports, true);
        assert.eq(Object.getOwnPropertySymbols(instance.exports).length, 1);
        assert.eq(Object.getOwnPropertySymbols(instance.exports)[0], Symbol.toStringTag);
        assert.throws(() => instance.exports[Symbol.toStringTag] = 42, TypeError, `Attempted to assign to readonly property.`);
        break;
    case "Memory":
        new WebAssembly.Memory({initial: 20});
        break;
    case "Table":
        new WebAssembly.Table({initial: 20, element: "funcref"});
        new WebAssembly.Table({initial: 20, maximum: 20, element: "funcref"});
        new WebAssembly.Table({initial: 20, maximum: 25, element: "funcref"});
        break;
    case "CompileError":
    case "LinkError":
    case "RuntimeError": {
        {
            const e = new WebAssembly[c];
            assert.eq(e instanceof WebAssembly[c], true);
            assert.eq(e instanceof Error, true);
            assert.eq(e instanceof TypeError, false);
            assert.eq(e.message, "");
            assert.eq(typeof e.stack, "string");
            const sillyString = "uh-oh!";
            const e2 = new WebAssembly[c](sillyString);
            assert.eq(e2.message, sillyString + " (evaluating 'new WebAssembly[c](sillyString)')");
        }
        {
            const e = WebAssembly[c]();
            assert.eq(e instanceof WebAssembly[c], true);
            assert.eq(e instanceof Error, true);
            assert.eq(e instanceof TypeError, false);
            assert.eq(e.message, "");
            assert.eq(typeof e.stack, "string");
            const sillyString = "uh-oh!";
            const e2 = WebAssembly[c](sillyString);
            assert.eq(e2.message, sillyString);
        }
    } break;
    default: throw new Error(`Implementation error: unexpected constructor property "${c}"`);
    }
}
