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

{
    // Test init from non-import.
    const builder = new Builder();

    builder.Type().End()
        .Function().End()
        .Global().GetGlobal("i32", 0, "immutable").End()
        .Export()
            .Function("getGlobal")
            .Global("global", 1)
        .End()
        .Code()

        .Function("getGlobal", { params: [], ret: "i32" })
        .GetGlobal(1)
        .End()

        .End()

    const bin = builder.WebAssembly();
    bin.trim();

    assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 26: get_global's index 0 exceeds the number of globals 0 (evaluating 'new WebAssembly.Module(bin.get())')");
}


{
    // Test import mutable.
    const builder = new Builder();

    builder.Type().End()
        .Import()
            .Global().I32("imp", "global", "mutable").End()
        .End()
        .Function().End()
        .Global().GetGlobal("i32", 0, "immutable").End()
        .Export()
            .Function("getGlobal")
            .Global("global", 1)
        .End()
        .Code()

        .Function("getGlobal", { params: [], ret: "i32" })
        .GetGlobal(1)
        .End()

        .End()

    const bin = builder.WebAssembly();
    bin.trim();

    assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 32: Mutable Globals aren't supported (evaluating 'new WebAssembly.Module(bin.get())')");
}

{
    // Test export mutable.
    const builder = new Builder();

    builder.Type().End()
        .Function().End()
        .Global().I32(0, "mutable").End()
        .Export()
            .Function("setGlobal")
            .Global("global", 0)
        .End()
        .Code()

        .Function("setGlobal", { params: [], ret: "i32" })
        .GetGlobal(1)
        .End()

        .End()

    const bin = builder.WebAssembly();
    bin.trim();

    assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 51: 1th Export isn't immutable, named 'global' (evaluating 'new WebAssembly.Module(bin.get())')");
}

{
    // Test set immutable.
    const builder = new Builder();

    builder.Type().End()
        .Function().End()
        .Global().I32(0, "immutable").End()
        .Export()
            .Function("setGlobal")
            .Global("global", 0)
        .End()
        .Code()

        .Function("setGlobal", { params: [], ret: "i32" })
        .I32Const(0)
        .SetGlobal(0)
        .End()

        .End()

    const bin = builder.WebAssembly();
    bin.trim();

    assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: set_global 0 is immutable, in function at index 0 (evaluating 'new WebAssembly.Module(bin.get())')");
}


{
    // Test set non-existant global.
    const builder = new Builder();

    builder.Type().End()
        .Function().End()
        .Global().I32(0, "immutable").End()
        .Export()
            .Function("setGlobal")
            .Global("global", 0)
        .End()
        .Code()

        .Function("setGlobal", { params: [], ret: "i32" })
        .I32Const(0)
        .SetGlobal(1)
        .End()

        .End()

    const bin = builder.WebAssembly();
    bin.trim();

    assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: set_global 1 of unknown global, limit is 1, in function at index 0 (evaluating 'new WebAssembly.Module(bin.get())')");
}


{
    // Test set to incorrect type
    const builder = new Builder();

    builder.Type().End()
        .Function().End()
        .Global().F32(0, "mutable").End()
        .Export()
            .Function("setGlobal")
        .End()
        .Code()

        .Function("setGlobal", { params: [], ret: "i32" })
        .I32Const(0)
        .SetGlobal(0)
        .End()

        .End()

    const bin = builder.WebAssembly();
    bin.trim();

    assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: set_global 0 with type F32 with a variable of type I32, in function at index 0 (evaluating 'new WebAssembly.Module(bin.get())')");
}

for ( let imp of [undefined, null, {}, () => {}, "number", new Number(4)]) {
    // Test import non-number.
    const builder = new Builder();

    builder.Type().End()
        .Import()
            .Global().I32("imp", "global", "immutable").End()
        .End()
        .Function().End()
        .Global().GetGlobal("i32", 0, "immutable").End()
        .Export()
            .Function("getGlobal")
            .Global("global", 1)
        .End()
        .Code()

        .Function("getGlobal", { params: [], ret: "i32" })
        .GetGlobal(1)
        .End()

        .End()

    const bin = builder.WebAssembly();
    bin.trim();

    const module = new WebAssembly.Module(bin.get());
    assert.throws(() => new WebAssembly.Instance(module, { imp: { global: imp } }), WebAssembly.LinkError, "imported global imp:global must be a number (evaluating 'new WebAssembly.Instance(module, { imp: { global: imp } })')");
}

{
    const builder = new Builder()
        .Type().End()
        .Global().I64(0, "immutable").End()
        .Export()
            .Global("bigInt", 0)
        .End();
    const module = new WebAssembly.Module(builder.WebAssembly().get());
    assert.throws(() => new WebAssembly.Instance(module), WebAssembly.LinkError, "exported global cannot be an i64 (evaluating 'new WebAssembly.Instance(module)')");
}

{
    const builder = new Builder()
        .Type().End()
        .Import()
            .Global().I64("imp", "global", "immutable").End()
        .End()
        .Function().End()
        .Global().GetGlobal("i64", 0, "immutable").End();
    const module = new WebAssembly.Module(builder.WebAssembly().get());
    assert.throws(() => new WebAssembly.Instance(module, { imp: { global: undefined } }), WebAssembly.LinkError, "imported global imp:global cannot be an i64 (evaluating 'new WebAssembly.Instance(module, { imp: { global: undefined } })')");
}
