"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppServiceProxyCommands = void 0;
const Utilities_1 = require("./../core/Utilities");
const Log_1 = require("./../core/Log");
const ste_events_1 = require("ste-events");
const CartoApp_1 = require("../app/CartoApp");
var AppServiceProxyCommands;
(function (AppServiceProxyCommands) {
    AppServiceProxyCommands["fsExists"] = "fsExists";
    AppServiceProxyCommands["fsFolderExists"] = "fsFolderExists";
    AppServiceProxyCommands["fsMkdir"] = "fsMkdir";
    AppServiceProxyCommands["fsReadUtf8File"] = "fsReadUtf8File";
    AppServiceProxyCommands["fsReadFile"] = "fsReadFile";
    AppServiceProxyCommands["fsWriteUtf8File"] = "fsWriteUtf8File";
    AppServiceProxyCommands["fsWriteFile"] = "fsWriteFile";
    AppServiceProxyCommands["fsReaddir"] = "fsReaddir";
    AppServiceProxyCommands["fsStat"] = "fsStat";
    AppServiceProxyCommands["getDirname"] = "getDirname";
    AppServiceProxyCommands["getDedicatedServerStatus"] = "getDedicatedServerStatus";
    AppServiceProxyCommands["getDedicatedServerProjectDeployDir"] = "getDedicatedServerProjectDir";
    AppServiceProxyCommands["getDedicatedServerWorldDeployDir"] = "getDedicatedServerWorldDir";
    AppServiceProxyCommands["getMinecraftGameProjectDeployDir"] = "getMinecraftGameProjectDeployDir";
    AppServiceProxyCommands["getMinecraftGameWorldDeployDir"] = "getMinecraftGameWorldDeployDir";
    AppServiceProxyCommands["getIsDev"] = "getIsDev";
    AppServiceProxyCommands["openFolder"] = "openFolder";
    AppServiceProxyCommands["shellOpenPath"] = "shellOpenPath";
    AppServiceProxyCommands["shellOpenFolderInExplorer"] = "shellOpenFolderInExplorer";
    AppServiceProxyCommands["webSocketCommand"] = "webSocketCommand";
    AppServiceProxyCommands["dedicatedServerCommand"] = "dedicatedServerCommand";
    AppServiceProxyCommands["startWebSocketServer"] = "startWebSocketServer";
    AppServiceProxyCommands["stopWebSocketServer"] = "stopWebSocketServer";
    AppServiceProxyCommands["startDedicatedServer"] = "startDedicatedServer";
    AppServiceProxyCommands["stopDedicatedServer"] = "stopDedicatedServer";
    AppServiceProxyCommands["shellRecycleItem"] = "shellRecycleItem";
    AppServiceProxyCommands["reloadMct"] = "reloadMct";
    AppServiceProxyCommands["minecraftShell"] = "minecraftShell";
    AppServiceProxyCommands["windowClose"] = "windowClose";
    AppServiceProxyCommands["windowRestore"] = "windowRestore";
    AppServiceProxyCommands["windowMove"] = "windowMove";
    AppServiceProxyCommands["logToConsole"] = "logToConsole";
    AppServiceProxyCommands["windowMinimize"] = "windowMinimize";
    AppServiceProxyCommands["windowMaximize"] = "windowMaximize";
    AppServiceProxyCommands["windowUpdate"] = "windowUpdate";
    AppServiceProxyCommands["windowLeftSide"] = "windowLeftSide";
    AppServiceProxyCommands["windowRightSide"] = "windowRightSide";
    AppServiceProxyCommands["getWindowState"] = "getWindowState";
    AppServiceProxyCommands["appGetPath"] = "appGetPath";
    AppServiceProxyCommands["updateIAgree"] = "updateIAgree";
    AppServiceProxyCommands["convertFile"] = "convertFile";
})(AppServiceProxyCommands = exports.AppServiceProxyCommands || (exports.AppServiceProxyCommands = {}));
class AppServiceProxy {
    static _api;
    static _pendingStringPromiseResolvers = [];
    static _pendingArrayBufferPromiseResolvers = [];
    static _pendingStringPromiseRejecters = [];
    static _pendingArrayPromiseRejecters = [];
    static _onMessage = new ste_events_1.EventDispatcher();
    static get onMessage() {
        return AppServiceProxy._onMessage.asEvent();
    }
    static get hasAppService() {
        return AppServiceProxy._api !== undefined;
    }
    static get hasAppServiceOrDebug() {
        return AppServiceProxy._api !== undefined || Utilities_1.default.isDebug;
    }
    static get hasAppServiceOrSim() {
        return AppServiceProxy._api !== undefined || Utilities_1.default.isAppSim;
    }
    static init() {
        // @ts-ignore
        if (typeof window !== "undefined") {
            // @ts-ignore
            AppServiceProxy._api = window.api;
            if (AppServiceProxy._api &&
                CartoApp_1.default.hostType !== CartoApp_1.HostType.vsCodeMainWeb &&
                CartoApp_1.default.hostType !== CartoApp_1.HostType.vsCodeWebWeb) {
                CartoApp_1.default.hostType = CartoApp_1.HostType.electronWeb;
                CartoApp_1.default.fullLocalStorage = true;
            }
        }
        if (AppServiceProxy._api !== undefined) {
            AppServiceProxy._api.receive("appsvc", AppServiceProxy._handleNewMessage);
            Log_1.default.onItemAdded.subscribe(AppServiceProxy._handleLog);
        }
    }
    static _handleLog(log, item) {
        AppServiceProxy.logToConsole(item.message);
    }
    static async logToConsole(message) {
        await AppServiceProxy.sendAsync(AppServiceProxyCommands.logToConsole, message);
    }
    static send(commandName, data) {
        if (AppServiceProxy._api === undefined) {
            if (Utilities_1.default.isAppSim) {
                Log_1.default.debugAlert("Command: " + commandName + " Data: " + data);
                return;
            }
            throw new Error("Not an Electron API");
        }
        if (commandName === AppServiceProxyCommands.fsWriteFile) {
            let content = data.content;
            if (content instanceof Uint8Array) {
                content = Utilities_1.default.uint8ArrayToBase64(content);
            }
            else if (data instanceof ArrayBuffer) {
                content = Utilities_1.default.arrayBufferToBase64(content);
            }
            else if (data instanceof Uint16Array ||
                data instanceof Uint32Array ||
                data instanceof Uint8ClampedArray ||
                data instanceof BigUint64Array) {
                Log_1.default.fail("Unsupported binary type encountered." + data);
            }
            data.content = content;
        }
        let result = undefined;
        try {
            result = AppServiceProxy._api.send("appweb", commandName, data);
        }
        catch (e) {
            let dataStr = data;
            if (typeof data === "object") {
                dataStr = JSON.stringify(data);
            }
            throw new Error("Error running command " + commandName + ", data: " + dataStr + ", error: " + e);
        }
        if (commandName === AppServiceProxyCommands.fsReadFile) {
            if (result === undefined || result.length === 0) {
                return undefined;
            }
            return Utilities_1.default.base64ToArrayBuffer(result);
        }
        return result;
    }
    static sendAsyncBinary(commandName, data) {
        const promise = new Promise(AppServiceProxy._arrayBufferPromiseHandler);
        if (AppServiceProxy._api === undefined) {
            if (Utilities_1.default.isAppSim) {
                Log_1.default.debugAlert("Command: " + commandName + " Data: " + data);
                return promise;
            }
            throw new Error("Not an Electron API");
        }
        const position = AppServiceProxy._pendingArrayBufferPromiseResolvers.length - 1;
        const commandStr = "bsync" + commandName + "|" + position;
        // Log.verbose("Sending async command '" + commandStr + "' + data: " + data);
        AppServiceProxy._api.send("appweb", commandStr, data);
        return promise;
    }
    static sendBinaryAsync(commandName, data) {
        const promise = new Promise(AppServiceProxy._stringPromiseHandler);
        if (AppServiceProxy._api === undefined) {
            if (Utilities_1.default.isAppSim) {
                Log_1.default.debugAlert("Command: " + commandName + " Data: " + data);
                return promise;
            }
            throw new Error("Not an Electron API");
        }
        let content = data.content;
        if (content instanceof Uint8Array) {
            content = Utilities_1.default.uint8ArrayToBase64(content);
        }
        else if (data instanceof ArrayBuffer) {
            content = Utilities_1.default.arrayBufferToBase64(content);
        }
        else if (data instanceof Uint16Array ||
            data instanceof Uint32Array ||
            data instanceof Uint8ClampedArray ||
            data instanceof BigUint64Array) {
            Log_1.default.fail("Unsupported binary type encountered." + data);
        }
        data.content = content;
        const position = AppServiceProxy._pendingStringPromiseResolvers.length - 1;
        const commandStr = "async" + commandName + "|" + position;
        // Log.verbose("Sending async command '" + commandStr + "' + data: " + data);
        AppServiceProxy._api.send("appweb", commandStr, data);
        return promise;
    }
    static sendAsync(commandName, data, ignoreInSim) {
        const promise = new Promise(AppServiceProxy._stringPromiseHandler);
        if (AppServiceProxy._api === undefined) {
            if (Utilities_1.default.isAppSim) {
                if (!ignoreInSim) {
                    Log_1.default.debugAlert("Command: " + commandName + " Data: " + data);
                }
                return promise;
            }
            throw new Error("Not an Electron API");
        }
        const position = AppServiceProxy._pendingStringPromiseResolvers.length - 1;
        const commandStr = "async" + commandName + "|" + position;
        // Do not uncomment this as it'll cause a loop.
        // Log.verbose("Sending async command '" + commandStr + "' + data: " + data);
        AppServiceProxy._api.send("appweb", commandStr, data);
        return promise;
    }
    static sendHost(serviceName, commandName, data) {
        if (AppServiceProxy._api === undefined) {
            throw new Error("Not an Electron API");
        }
        if (typeof data === "object") {
            data = JSON.stringify(data);
        }
        else if (typeof data !== "string") {
            data = data.toString();
        }
        AppServiceProxy._api.send(serviceName, commandName, data);
    }
    static openLinkExternal(url) {
        try {
            // @ts-ignore
            if (typeof window !== "undefined") {
                // @ts-ignore
                window.open(url, "_blank");
            }
        }
        catch (e) { }
    }
    static _arrayBufferPromiseHandler(resolve, reject) {
        const position = AppServiceProxy._pendingArrayBufferPromiseResolvers.length;
        AppServiceProxy._pendingArrayBufferPromiseResolvers[position] = resolve;
        AppServiceProxy._pendingStringPromiseRejecters[position] = reject;
    }
    static _stringPromiseHandler(resolve, reject) {
        const position = AppServiceProxy._pendingStringPromiseResolvers.length;
        AppServiceProxy._pendingStringPromiseResolvers[position] = resolve;
        AppServiceProxy._pendingStringPromiseRejecters[position] = reject;
    }
    static _handleNewMessage(args) {
        if (args !== null && args.length > 0) {
            if (args.startsWith("async")) {
                const argSplit = args.split("|");
                if (argSplit.length > 2) {
                    const index = parseInt(argSplit[1]);
                    if (index >= 0) {
                        const promiseResolver = AppServiceProxy._pendingStringPromiseResolvers[index];
                        // NOTE: Since logging goes from browser to client and then async is complete,
                        // DO NOT log inside of here or otherwise you may cause a loop.
                        let val = argSplit[2];
                        if (val === "<undefined>") {
                            val = undefined;
                        }
                        promiseResolver(val);
                    }
                }
            }
            else if (args.startsWith("bsync")) {
                const argSplit = args.split("|");
                if (argSplit.length > 2) {
                    const index = parseInt(argSplit[1]);
                    if (index >= 0) {
                        const promiseResolver = AppServiceProxy._pendingArrayBufferPromiseResolvers[index];
                        // NOTE: Since logging goes from browser to client and then async is complete,
                        // DO NOT log inside of here or otherwise you may cause a loop.
                        let val = undefined;
                        if (argSplit[2] !== "<undefined>") {
                            val = Utilities_1.default.base64ToArrayBuffer(argSplit[2]);
                        }
                        promiseResolver(val);
                    }
                }
            }
            else {
                const firstPipe = args.indexOf("|");
                if (firstPipe >= 0) {
                    AppServiceProxy._onMessage.dispatch(args.substring(0, firstPipe), args.substring(firstPipe + 1, args.length));
                }
            }
        }
    }
}
exports.default = AppServiceProxy;

//# sourceMappingURL=../maps/core/AppServiceProxy.js.map
