"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.pollEvent = exports.exitGame = exports.quitting = exports.setAntialias = exports.setSsaoQuality = exports.setShadowQuality = exports.toggleFullscreen = exports.tick = exports.render = exports.GL = exports.writeString = exports.getLength = exports.setLength = exports.loadAudio = exports.nextALBuffer = exports.AudioChannels = exports.AudioBitDepth = exports.AudioFormat = exports.ready = exports.init = exports.commandGet = exports.printString = exports.command = exports.buffers = exports.poll = exports.measureText = exports.paste = exports.copy = exports.pollUSB = exports.nextPool = exports.nextBuffer = exports.startTicking = exports.KMOD = exports.EventType = exports.Command = exports.BufferKind = void 0;
const util_1 = require("util");
const cenums_1 = require("./cenums");
var UserEvent;
(function (UserEvent) {
    UserEvent[UserEvent["AdapterConnected"] = 0] = "AdapterConnected";
    UserEvent[UserEvent["AdapterDisconnected"] = 1] = "AdapterDisconnected";
})(UserEvent || (UserEvent = {}));
var BufferKind;
(function (BufferKind) {
    BufferKind[BufferKind["length"] = 0] = "length";
    BufferKind[BufferKind["pool"] = 1] = "pool";
    BufferKind[BufferKind["command"] = 2] = "command";
    BufferKind[BufferKind["returns"] = 3] = "returns";
    BufferKind[BufferKind["events"] = 4] = "events";
    BufferKind[BufferKind["flags"] = 5] = "flags";
    BufferKind[BufferKind["adapter"] = 6] = "adapter";
    BufferKind[BufferKind["strings"] = 7] = "strings";
})(BufferKind = exports.BufferKind || (exports.BufferKind = {}));
var Command;
(function (Command) {
    Command[Command["nothing"] = 0] = "nothing";
    Command[Command["audioPlay"] = 1] = "audioPlay";
    Command[Command["audioPause"] = 2] = "audioPause";
    Command[Command["audioStop"] = 3] = "audioStop";
    Command[Command["audioVolume"] = 4] = "audioVolume";
    Command[Command["audioStopAll"] = 5] = "audioStopAll";
    Command[Command["audioPauseAll"] = 6] = "audioPauseAll";
    Command[Command["audioPlayAll"] = 7] = "audioPlayAll";
    Command[Command["toggleFullscreen"] = 8] = "toggleFullscreen";
    Command[Command["printString"] = 9] = "printString";
    Command[Command["fillString"] = 10] = "fillString";
    Command[Command["strokeString"] = 11] = "strokeString";
    Command[Command["fillColor"] = 12] = "fillColor";
    Command[Command["strokeColor"] = 13] = "strokeColor";
})(Command = exports.Command || (exports.Command = {}));
var EventType;
(function (EventType) {
    EventType[EventType["Resize"] = 0] = "Resize";
    EventType[EventType["MouseMove"] = 1] = "MouseMove";
    EventType[EventType["MouseUp"] = 2] = "MouseUp";
    EventType[EventType["MouseDown"] = 3] = "MouseDown";
    EventType[EventType["MouseWheel"] = 4] = "MouseWheel";
    EventType[EventType["KeyUp"] = 5] = "KeyUp";
    EventType[EventType["KeyDown"] = 6] = "KeyDown";
    EventType[EventType["Text"] = 7] = "Text";
    EventType[EventType["ControllerAdded"] = 8] = "ControllerAdded";
    EventType[EventType["ControllerRemoved"] = 9] = "ControllerRemoved";
    EventType[EventType["ControllerRemapped"] = 10] = "ControllerRemapped";
    EventType[EventType["ControllerAxis"] = 11] = "ControllerAxis";
    EventType[EventType["ControllerButtonUp"] = 12] = "ControllerButtonUp";
    EventType[EventType["ControllerButtonDown"] = 13] = "ControllerButtonDown";
    EventType[EventType["Quit"] = 14] = "Quit";
    EventType[EventType["AdapterConnected"] = 15] = "AdapterConnected";
    EventType[EventType["AdapterDisconnected"] = 16] = "AdapterDisconnected";
})(EventType = exports.EventType || (exports.EventType = {}));
var KMOD;
(function (KMOD) {
    KMOD[KMOD["NONE"] = 0] = "NONE";
    KMOD[KMOD["LSHIFT"] = 1] = "LSHIFT";
    KMOD[KMOD["RSHIFT"] = 2] = "RSHIFT";
    KMOD[KMOD["LCTRL"] = 64] = "LCTRL";
    KMOD[KMOD["RCTRL"] = 128] = "RCTRL";
    KMOD[KMOD["LALT"] = 256] = "LALT";
    KMOD[KMOD["RALT"] = 512] = "RALT";
    KMOD[KMOD["LGUI"] = 1024] = "LGUI";
    KMOD[KMOD["RGUI"] = 2048] = "RGUI";
    KMOD[KMOD["NUM"] = 4096] = "NUM";
    KMOD[KMOD["CAPS"] = 8192] = "CAPS";
    KMOD[KMOD["MODE"] = 16384] = "MODE";
    KMOD[KMOD["RESERVED"] = 32768] = "RESERVED";
    KMOD[KMOD["CTRL"] = 192] = "CTRL";
    KMOD[KMOD["SHIFT"] = 3] = "SHIFT";
    KMOD[KMOD["ALT"] = 768] = "ALT";
    KMOD[KMOD["GUI"] = 3072] = "GUI";
})(KMOD = exports.KMOD || (exports.KMOD = {}));
const enableSegfaultHandler = true;
if (enableSegfaultHandler) {
    try {
        const SegfaultHandler = require('segfault-handler');
        SegfaultHandler.registerHandler('crash.log', (_signal, _address, _stack) => {
        });
    }
    catch (err) {
        console.warn('Unable to load segfault-handler');
    }
}
let Native;
try {
    Native = require('bindings')('antistatic.node');
}
catch (e) {
    console.error(`Unable to start Antistatic: may need shared libraries.
  Installers can be downloaded from:
  OpenAL: https://www.openal.org/downloads/oalinst.zip
  Microsoft Visual C++ runtime: https://aka.ms/vs/15/release/vc_redist.x64.exe

Detailed error:`);
    throw e;
}
exports.startTicking = Native.startTicking;
exports.nextBuffer = Native.nextBuffer;
exports.nextPool = Native.nextPool;
exports.pollUSB = Native.pollUSB;
exports.copy = Native.copy;
exports.paste = Native.paste;
exports.measureText = Native.measureText;
const poll = () => {
    let eventByteLength = 0;
    const evts = exports.buffers.events;
    Native.poll();
    eventByteLength = exports.buffers.length[BufferKind.events];
    for (let b = 0; b < eventByteLength;) {
        const kind = evts.getUint16(b, true);
        b = b + 2;
        switch (kind) {
            case 1616:
                events.push({
                    type: 11,
                    which: evts.getInt32(b, true),
                    axis: evts.getUint8(b + 4),
                    value: evts.getFloat32(b + 5, true),
                });
                b = b + 9;
                break;
            case 1617:
            case 1618:
                events.push({
                    type: kind === 1617
                        ? 13
                        : 12,
                    which: evts.getInt32(b, true),
                    button: evts.getUint8(b + 4),
                    state: evts.getUint8(b + 5),
                });
                b = b + 6;
                break;
            case 1619:
                events.push({
                    type: 8,
                    which: evts.getInt32(b, true),
                });
                b = b + 4;
                break;
            case 1620:
                events.push({
                    type: 9,
                    which: evts.getInt32(b, true),
                });
                b = b + 4;
                break;
            case 1621:
                events.push({
                    type: 10,
                    which: evts.getInt32(b, true),
                });
                b = b + 4;
                break;
            case 768:
            case 769:
                events.push({
                    type: kind === 768 ? 6 : 5,
                    pressed: kind === 768,
                    code: evts.getUint16(b, true),
                    sym: evts.getUint32(b + 2, true),
                    key: cenums_1.SDLK_LOOKUP[evts.getUint32(b + 2, true)],
                    mod: evts.getUint16(b + 6, true),
                    repeat: evts.getUint8(b + 8) !== 0,
                });
                b = b + 9;
                break;
            case 1024:
                events.push({
                    type: 1,
                    x: evts.getInt32(b, true),
                    y: evts.getInt32(b + 4, true),
                });
                b = b + 8;
                break;
            case 1025:
            case 1026:
                events.push({
                    type: kind === 1025
                        ? 3
                        : 2,
                    x: evts.getInt32(b, true),
                    y: evts.getInt32(b + 4, true),
                    pressed: kind === 1025,
                    button: evts.getUint8(b + 8) - 1,
                });
                b = b + 9;
                break;
            case 771: {
                const slen = evts.getUint8(b);
                b = b + 1;
                for (let i = 0; i < slen; i++) {
                    strslice[i] = evts.getUint8(b + i);
                }
                events.push({
                    type: 7,
                    text: decoder.decode(strslice.slice(0, slen)),
                });
                b = b + slen;
                break;
            }
            case 512:
                switch (evts.getUint8(b)) {
                    case 6:
                        events.push({
                            type: 0,
                            x: evts.getInt32(b + 1, true),
                            y: evts.getInt32(b + 5, true),
                        });
                        b = b + 9;
                        break;
                    default:
                        console.warn('got unknown window event');
                }
                break;
            case 32768:
                console.log('got user event');
                switch (evts.getUint16(b)) {
                    case 0:
                        events.push({
                            type: 15,
                        });
                        b = b + 6;
                        break;
                    case 1:
                        events.push({
                            type: 16,
                        });
                        b = b + 6;
                        break;
                    default:
                        console.warn('got unknown user event');
                }
                b = b + 2;
                break;
            case 256:
                events.push({
                    type: 14,
                });
                break;
            default:
                console.warn('got unknown event:', kind);
        }
    }
};
exports.poll = poll;
const coreBufferCount = 2;
const namedBufferCount = 8;
const maxBufferCount = 256;
let alBufferCount = 0;
exports.buffers = {
    length: null,
    pool: null,
    command: null,
    returns: null,
    events: null,
    flags: null,
    adapter: null,
    strings: null,
};
global.buffers = exports.buffers;
const DefaultLengths = {
    length: maxBufferCount,
    pool: 2048,
    command: 4096,
    returns: 2048,
    events: 2048,
    flags: 1,
    adapter: 37,
    strings: 65536,
};
const command = (c, ...args) => {
    if (args.length + 1 + exports.buffers.length[BufferKind.command]
        > exports.buffers.command.length) {
        return;
    }
    pushUInt(BufferKind.command, c);
    for (let i = 0; i < args.length; i++) {
        pushFloat(BufferKind.command, args[i]);
    }
};
exports.command = command;
const printString = (s) => {
    const [ptr, len] = exports.writeString(s);
    exports.command(9, ptr, len);
};
exports.printString = printString;
const returnPromises = [];
const returnIndices = new Float64Array(DefaultLengths.returns);
const commandGet = (c, ...args) => new Promise((resolve, _) => {
    const index = exports.buffers.length[BufferKind.command];
    if (args.length + 1 + exports.buffers.length[BufferKind.command]
        > exports.buffers.command.length) {
        resolve(-1);
        return;
    }
    pushUInt(BufferKind.command, c);
    for (let i = 0; i < args.length; i++) {
        pushFloat(BufferKind.command, args[i]);
    }
    returnIndices[returnPromises.length] = index;
    returnPromises.push(resolve);
});
exports.commandGet = commandGet;
const allBufferIds = [];
for (let i = 0; i < namedBufferCount; i++) {
    allBufferIds.push(exports.buffers[BufferKind[i]]);
}
const init = () => {
    exports.buffers.length = new Uint32Array(Native.initBuffer(BufferKind.length, DefaultLengths.length * Uint32Array.BYTES_PER_ELEMENT));
    exports.buffers.pool = Native.initBuffer(BufferKind.pool, DefaultLengths.pool);
    exports.buffers.command = new Float64Array(Native.initBuffer(BufferKind.command, DefaultLengths.command * Float64Array.BYTES_PER_ELEMENT));
    exports.buffers.returns = new Float64Array(Native.initBuffer(BufferKind.returns, DefaultLengths.returns * Float64Array.BYTES_PER_ELEMENT));
    exports.buffers.events = new DataView(Native.initBuffer(BufferKind.events, DefaultLengths.events * Float64Array.BYTES_PER_ELEMENT));
    exports.buffers.flags = new Uint32Array(Native.initBuffer(BufferKind.flags, DefaultLengths.flags * Uint32Array.BYTES_PER_ELEMENT));
    exports.buffers.adapter = Buffer.from(Native.initBuffer(BufferKind.adapter, DefaultLengths.adapter * Uint8Array.BYTES_PER_ELEMENT));
    exports.buffers.strings = Buffer.from(Native.initBuffer(BufferKind.strings, DefaultLengths.strings * Uint8Array.BYTES_PER_ELEMENT));
    for (let i = 0; i < namedBufferCount; i++) {
        allBufferIds[i] = exports.buffers[BufferKind[i]];
    }
    exports.buffers.length[0] = exports.buffers.length.length;
    for (let i = 1; i < exports.buffers.length.length; i++) {
        exports.buffers.length[i] = 0;
    }
    exports.buffers.flags[0] = 0;
};
exports.init = init;
exports.init();
const ready = () => {
    Native.ready();
};
exports.ready = ready;
var AudioFormat;
(function (AudioFormat) {
    AudioFormat[AudioFormat["mono8"] = Native.AL_FORMAT_MONO8] = "mono8";
    AudioFormat[AudioFormat["mono16"] = Native.AL_FORMAT_MONO16] = "mono16";
    AudioFormat[AudioFormat["stereo8"] = Native.AL_FORMAT_STEREO8] = "stereo8";
    AudioFormat[AudioFormat["stereo16"] = Native.AL_FORMAT_STEREO16] = "stereo16";
})(AudioFormat = exports.AudioFormat || (exports.AudioFormat = {}));
exports.AudioBitDepth = {
    [AudioFormat.mono8]: 8,
    [AudioFormat.mono16]: 16,
    [AudioFormat.stereo8]: 8,
    [AudioFormat.stereo16]: 16,
};
exports.AudioChannels = {
    [AudioFormat.mono8]: 1,
    [AudioFormat.mono16]: 1,
    [AudioFormat.stereo8]: 2,
    [AudioFormat.stereo16]: 2,
};
const nextALBuffer = (buffer, format, sampleRate) => {
    Native.initALBuffer(alBufferCount, buffer, format, sampleRate >>> 0);
    alBufferCount++;
    return alBufferCount - 1;
};
exports.nextALBuffer = nextALBuffer;
const loadAudio = async (path, wordSize, channels) => {
    Native.loadAudio(alBufferCount, path, wordSize, channels);
    alBufferCount++;
    return alBufferCount - 1;
};
exports.loadAudio = loadAudio;
const setLength = (id, length) => {
    exports.buffers.length[id] = length >>> 0;
};
exports.setLength = setLength;
const getLength = (id) => exports.buffers.length[id] >>> 0;
exports.getLength = getLength;
const pushInt = (id, val) => {
    ;
    allBufferIds[id][exports.buffers.length[id]] = val | 0;
    exports.buffers.length[id]++;
};
const pushUInt = (id, val) => {
    ;
    allBufferIds[id][exports.buffers.length[id]] = val >>> 0;
    exports.buffers.length[id]++;
};
const pushFloat = (id, val) => {
    ;
    allBufferIds[id][exports.buffers.length[id]] = +val;
    exports.buffers.length[id]++;
};
const strStats = [0, 0];
const writeString = (val) => {
    let len = 0;
    const blen = exports.buffers.length[BufferKind.strings];
    if (val.length === 0 || val.length + blen > exports.buffers.strings.length) {
        strStats[0] = blen;
        strStats[1] = 0;
        return strStats;
    }
    len = exports.buffers.strings.write(val, blen, 'utf8');
    strStats[0] = blen;
    strStats[1] = len;
    exports.buffers.length[BufferKind.strings] = blen + len;
    return strStats;
};
exports.writeString = writeString;
exports.GL = {
    constructor() { },
    init() {
    },
    compileShader(name, isVertex, source) {
        return Native.compileShader(name, isVertex, source) === 0;
    },
    checkShaders() {
        return Native.checkShaders() === 0;
    },
    setBuffers(bufferIds) {
        if (bufferIds.length !== 29) {
            console.error('setBuffers: need 29 buffers, got', bufferIds.length);
        }
        const pool = Native.nextPool(bufferIds.length * Uint16Array.BYTES_PER_ELEMENT);
        const u8 = new Uint16Array(pool[0]);
        for (let i = 0; i < bufferIds.length; i++) {
            u8[i] = bufferIds[i];
        }
        return Native.setBuffers(pool[1]);
    },
};
const decoder = new util_1.TextDecoder('utf-8');
const strslice = new Uint8Array(32);
exports.render = Native.render;
const tick = () => {
    Native.tick();
    for (let i = 0; i < returnPromises.length; i++) {
        returnPromises[i](exports.buffers.returns[returnIndices[i]]);
    }
    for (let i = coreBufferCount; i < namedBufferCount; i++) {
        exports.buffers.length[i] = 0;
    }
};
exports.tick = tick;
const toggleFullscreen = () => {
    exports.command(8);
};
exports.toggleFullscreen = toggleFullscreen;
exports.setShadowQuality = Native.setShadowQuality;
exports.setSsaoQuality = Native.setSsaoQuality;
exports.setAntialias = Native.setAntialias;
let quitResolve = null;
exports.quitting = new Promise(resolve => {
    quitResolve = resolve;
});
const exitGame = () => quitResolve(null);
exports.exitGame = exitGame;
exports.quitting.then(() => {
    console.log('Cleaning up');
    Native.quit();
    console.log('Cleanup OK');
});
const events = [];
const pollEvent = () => {
    if (events.length === 0) {
        return null;
    }
    return events.shift();
};
exports.pollEvent = pollEvent;
//# sourceMappingURL=native.js.map