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

// FIXME: add the following: https://bugs.webkit.org/show_bug.cgi?id=171936
//  - add set() and shadow memory, this requires tracking when memory is shared
//  - Support: empty, exported
//  - Imported memory created through the JS API (both before and after instantiation, to cause recompilation)
//  - recursive calls (randomly call other instance's exports, potentially exhausting stack)
//  - Simplify code by allowing .Code().ExportFunction(...) in builder

const tune = {
    numRandomIterations: 64,
    numRandomInvokes: 4,
    maxInitial: 8,
    maxMax: 8,
    maxGrow: 8,
    memoryGetCount: 1024,
};

const pageSize = 64 * 1024; // As determined by the WebAssembly specification.

let logString = "";
let log = what => logString += '\n' + what;

let instances = [];

const insert = (builder, importObject = undefined) => {
    const location = (Math.random() * instances.length) | 0;
    instances.splice(location, 0, new WebAssembly.Instance(new WebAssembly.Module(builder.WebAssembly().get()), importObject));
}
const initialMaxObject = hasMax => {
    const initial = (Math.random() * tune.maxInitial) | 0;
    if (!hasMax)
        return { initial: initial, max: undefined };
    const max = initial + ((Math.random() * tune.maxMax) | 0);
    return { initial: initial, max: max };
};
const initialMaxObjectFrom = instance => {
    const hasMax = instance.exports["max"] !== undefined;
    const initial = (Math.random() * instance.exports.initial()) | 0;
    if (!hasMax)
        return { initial: initial };
    const max = Math.max(initial, instance.exports.max()) + ((Math.random() * tune.maxMax) | 0);
    return { initial: initial, max: max };
};

const action = {
    '- delete': () => {
        for (let count = 1 + (Math.random() * instances.length) | 0; instances.length && count; --count) {
            const which = (Math.random() * instances.length) | 0;
            log(`    delete ${which} / ${instances.length}`);
            instances.splice(which, 1);
        }
    },
    '^ invoke': () => {
        if (!instances.length) {
            log(`    nothing to invoke`);
            return;
        }
        for (let iterations = 0; iterations < tune.numRandomInvokes; ++iterations) {
            const whichInstance = (Math.random() * instances.length) | 0;
            const instance = instances[whichInstance];
            const whichExport = (Math.random() * Object.keys(instance.exports).length) | 0;
            log(`    instances[${whichInstance}].${Object.keys(instance.exports)[whichExport]}()`);
            switch (Object.keys(instance.exports)[whichExport]) {
            default:
                throw new Error(`Implementation problem for key '${Object.keys(instance.exports)[whichExport]}'`);
            case 'func':
                assert.eq(instance.exports.func(), 42);
                break;
            case 'throws': {
                let threw = false;
                let address = 0;
                if (instance.exports["current"]) {
                    // The instance has a memory.
                    const current = instance.exports.current();
                    const max = instance.exports["max"] ? instance.exports.max() : (1 << 15);
                    address = pageSize * (current + ((Math.random() * (max - current)) | 0));
                }
                // No memory in this instance.
                try { instance.exports.throws(address); }
                catch (e) { threw = true; }
                assert.truthy(threw);
            } break;
            case 'get': {
                const current = instance.exports.current();
                for (let access = tune.memoryGetCount; current && access; --access) {
                    const address = (Math.random() * (current * pageSize - 4)) | 0;
                    assert.eq(instance.exports.get(address), 0);
                }
            } break;
            case 'current':
                assert.le(instance.exports.initial(), instance.exports.current());
                break;
            case 'initial':
                assert.le(0, instance.exports.initial());
                break;
            case 'max':
                assert.le(instance.exports.initial(), instance.exports.max());
                assert.le(instance.exports.current(), instance.exports.max());
                break;
            case 'memory': {
                const current = instance.exports.current();
                assert.eq(instance.exports.memory.buffer.byteLength, current * pageSize);
                for (let access = tune.memoryGetCount; current && access; --access) {
                    const address = (Math.random() * (current * pageSize - 4)) | 0;
                    assert.eq(instance.exports.get(address), 0);
                }
            } break;
            case 'grow': {
                const current = instance.exports.current();
                const by = (Math.random() * tune.maxGrow) | 0;
                const hasMax = instance.exports["max"] !== undefined;
                const result = instance.exports.grow(current + by);
                log(`        Grow from ${current} (max ${hasMax ? instance.exports.max() : "none"}) to ${current + by} returned ${result}, current now ${instance.exports.current()}`);
                assert.le(current, instance.exports.current());
                if (result === -1)
                    assert.eq(current, instance.exports.current());
                if (hasMax)
                    assert.le(instance.exports.current(), instance.exports.max());
            } break;
            }
        }
    },
    '+ memory: none': () => {
        const builder = (new Builder())
              .Type().End()
              .Function().End()
              .Export().Function("func").Function("throws").End()
              .Code()
                  .Function("func", { params: [], ret: "i32" }).I32Const(42).Return().End()
                  .Function("throws", { params: ["i32"] }).Unreachable().Return().End()
              .End();
        insert(builder);
    },
    '+ memory: empty, section': () => {
        const builder = (new Builder())
              .Type().End()
              .Function().End()
              .Memory().InitialMaxPages(0, 0).End()
              .Export().Function("func").Function("throws").Function("current").Function("initial").Function("grow").Function("max").End()
              .Code()
                  .Function("func", { params: [], ret: "i32" }).I32Const(42).Return().End()
                  .Function("throws", { params: ["i32"] }).GetLocal(0).I32Load(2, 0).Return().End()
                  .Function("current", { params: [], ret: "i32" }).CurrentMemory(0).Return().End()
                  .Function("grow", { params: ["i32"], ret: "i32" }).GetLocal(0).GrowMemory(0).Return().End()
                  .Function("initial", { params: [], ret: "i32" }).I32Const(0).Return().End()
                  .Function("max", { params: [], ret: "i32" }).I32Const(0).Return().End()
              .End();
        insert(builder);
    },
    '+ memory: section': () => {
        const initialMax = initialMaxObject(false);
        const builder = (new Builder())
              .Type().End()
              .Function().End()
              .Memory().InitialMaxPages(initialMax.initial, initialMax.max).End()
              .Export().Function("func").Function("throws").Function("get").Function("current").Function("initial").Function("grow").End()
              .Code()
                  .Function("func", { params: [], ret: "i32" }).I32Const(42).Return().End()
                  .Function("throws", { params: ["i32"] }).GetLocal(0).I32Load(2, 0).Return().End()
                  .Function("get", { params: ["i32"], ret: "i32" }).GetLocal(0).I32Load(2, 0).Return().End()
                  .Function("current", { params: [], ret: "i32" }).CurrentMemory(0).Return().End()
                  .Function("grow", { params: ["i32"], ret: "i32" }).GetLocal(0).GrowMemory(0).Return().End()
                  .Function("initial", { params: [], ret: "i32" }).I32Const(initialMax.initial).Return().End()
              .End();
        insert(builder);
    },
    '+ memory: section, max': () => {
        const initialMax = initialMaxObject(true);
        const builder = (new Builder())
              .Type().End()
              .Function().End()
              .Memory().InitialMaxPages(initialMax.initial, initialMax.max).End()
              .Export().Function("func").Function("throws").Function("get").Function("current").Function("initial").Function("grow").Function("max").End()
              .Code()
                  .Function("func", { params: [], ret: "i32" }).I32Const(42).Return().End()
                  .Function("throws", { params: ["i32"] }).GetLocal(0).I32Load(2, 0).Return().End()
                  .Function("get", { params: ["i32"], ret: "i32" }).GetLocal(0).I32Load(2, 0).Return().End()
                  .Function("current", { params: [], ret: "i32" }).CurrentMemory(0).Return().End()
                  .Function("grow", { params: ["i32"], ret: "i32" }).GetLocal(0).GrowMemory(0).Return().End()
                  .Function("initial", { params: [], ret: "i32" }).I32Const(initialMax.initial).Return().End()
                  .Function("max", { params: [], ret: "i32" }).I32Const(initialMax.max).Return().End()
              .End();
        insert(builder);
    },
    '+ memory: section, exported': () => {
        const initialMax = initialMaxObject(false);
        const builder = (new Builder())
              .Type().End()
              .Function().End()
              .Memory().InitialMaxPages(initialMax.initial, initialMax.max).End()
              .Export()
                  .Function("func").Function("throws").Function("get").Function("current").Function("initial")
                  .Memory("memory", 0)
              .End()
              .Code()
                  .Function("func", { params: [], ret: "i32" }).I32Const(42).Return().End()
                  .Function("throws", { params: ["i32"] }).GetLocal(0).I32Load(2, 0).Return().End()
                  .Function("get", { params: ["i32"], ret: "i32" }).GetLocal(0).I32Load(2, 0).Return().End()
                  .Function("current", { params: [], ret: "i32" }).CurrentMemory(0).Return().End()
                  .Function("grow", { params: ["i32"], ret: "i32" }).GetLocal(0).GrowMemory(0).Return().End()
                  .Function("initial", { params: [], ret: "i32" }).I32Const(initialMax.initial).Return().End()
              .End();
        insert(builder);
    },
    '+ memory: section, exported, max': () => {
        const initialMax = initialMaxObject(true);
        const builder = (new Builder())
              .Type().End()
              .Function().End()
              .Memory().InitialMaxPages(initialMax.initial, initialMax.max).End()
              .Export()
                  .Function("func").Function("throws").Function("get").Function("current").Function("initial").Function("grow").Function("max")
                  .Memory("memory", 0)
              .End()
              .Code()
                  .Function("func", { params: [], ret: "i32" }).I32Const(42).Return().End()
                  .Function("throws", { params: ["i32"] }).GetLocal(0).I32Load(2, 0).Return().End()
                  .Function("get", { params: ["i32"], ret: "i32" }).GetLocal(0).I32Load(2, 0).Return().End()
                  .Function("current", { params: [], ret: "i32" }).CurrentMemory(0).Return().End()
                  .Function("grow", { params: ["i32"], ret: "i32" }).GetLocal(0).GrowMemory(0).Return().End()
                  .Function("initial", { params: [], ret: "i32" }).I32Const(initialMax.initial).Return().End()
                  .Function("max", { params: [], ret: "i32" }).I32Const(initialMax.max).Return().End()
              .End();
        insert(builder);
    },
    '+ memory: imported, exported': () => {
        let importFrom;
        for (let idx = 0; idx < instances.length; ++idx)
            if (instances[idx].exports.memory) {
                importFrom = instances[idx];
                break;
            }
        if (!importFrom)
            return; // No memory could be imported.
        const initialMax = initialMaxObjectFrom(importFrom);
        if (importFrom.exports["max"] === undefined) {
            const builder = (new Builder())
                  .Type().End()
                  .Import().Memory("imp", "memory", initialMax).End()
                  .Function().End()
                  .Export()
                      .Function("func").Function("throws").Function("get").Function("current").Function("initial")
                      .Memory("memory", 0)
                  .End()
                  .Code()
                      .Function("func", { params: [], ret: "i32" }).I32Const(42).Return().End()
                      .Function("throws", { params: ["i32"] }).GetLocal(0).I32Load(2, 0).Return().End()
                      .Function("get", { params: ["i32"], ret: "i32" }).GetLocal(0).I32Load(2, 0).Return().End()
                      .Function("current", { params: [], ret: "i32" }).CurrentMemory(0).Return().End()
                      .Function("grow", { params: ["i32"], ret: "i32" }).GetLocal(0).GrowMemory(0).Return().End()
                      .Function("initial", { params: [], ret: "i32" }).I32Const(initialMax.initial).Return().End()
                  .End();
            insert(builder, { imp: { memory: importFrom.exports.memory } });
        } else {
            const builder = (new Builder())
                  .Type().End()
                  .Import().Memory("imp", "memory", initialMax).End()
                  .Function().End()
                  .Export()
                      .Function("func").Function("throws").Function("get").Function("current").Function("initial").Function("grow").Function("max")
                      .Memory("memory", 0)
                  .End()
                  .Code()
                      .Function("func", { params: [], ret: "i32" }).I32Const(42).Return().End()
                      .Function("throws", { params: ["i32"] }).GetLocal(0).I32Load(2, 0).Return().End()
                      .Function("get", { params: ["i32"], ret: "i32" }).GetLocal(0).I32Load(2, 0).Return().End()
                      .Function("current", { params: [], ret: "i32" }).CurrentMemory(0).Return().End()
                      .Function("grow", { params: ["i32"], ret: "i32" }).GetLocal(0).GrowMemory(0).Return().End()
                      .Function("initial", { params: [], ret: "i32" }).I32Const(initialMax.initial).Return().End()
                      .Function("max", { params: [], ret: "i32" }).I32Const(initialMax.max).Return().End()
                  .End();
            insert(builder, { imp: { memory: importFrom.exports.memory } });
        }
    },
};
const numActions = Object.keys(action).length;
const performAction = () => {
    const which = (Math.random() * numActions) | 0;
    const key = Object.keys(action)[which];
    log(`${key}:`);
    action[key]();
};

try {
    for (let iteration = 0; iteration < tune.numRandomIterations; ++iteration)
        performAction();
    log(`Finalizing:`);
    // Finish by deleting the instances in a random order.
    while (instances.length)
        action["- delete"]();
} catch (e) {
    // Ignore OOM while fuzzing. It can just happen.
    if (e.message !== "Out of memory") {
        print(`Failed: ${e}`);
        print(logString);
        throw e;
    }
}
