"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module IModelApp
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.LocalhostIpcApp = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const core_common_1 = require("@itwin/core-common");
const IpcApp_1 = require("./IpcApp");
const IModelApp_1 = require("./IModelApp");
const Symbols_1 = require("./common/internal/Symbols");
class LocalTransport extends core_common_1.IpcWebSocketTransport {
    _client;
    _next;
    _pending = [];
    constructor(opts) {
        super();
        let url;
        if (opts?.localhostIpcApp?.socketUrl) {
            url = opts?.localhostIpcApp?.socketUrl;
        }
        else {
            const port = opts?.localhostIpcApp?.socketPort ?? 3002;
            url = new URL(`ws://localhost:${port}/`);
        }
        this._client = new WebSocket(url);
        this._next = -1;
        this._client.addEventListener("open", () => {
            const pending = (0, core_bentley_1.expectDefined)(this._pending);
            this._pending = undefined;
            pending.forEach((m) => this.send(m));
        });
        this._client.addEventListener("message", async (event) => {
            const message = await this.notifyIncoming(event.data, this._client);
            if (core_common_1.IpcWebSocketMessage.skip(message)) {
                return;
            }
            for (const listener of core_common_1.IpcWebSocket.receivers)
                listener({}, message);
        });
    }
    send(message) {
        if (this._pending) {
            this._pending.push(message);
            return;
        }
        message.sequence = ++this._next;
        const parts = this.serialize(message);
        parts.forEach((part) => this._client.send(part));
    }
}
class LocalSession extends core_common_1.IpcSession {
    async handleRpc(info) {
        return IpcApp_1.IpcApp[Symbols_1._callIpcChannel](core_common_1.rpcOverIpcStrings.channelName, "request", info);
    }
}
/**
 * To be used only by test applications that want to test web-based editing using localhost.
 *  @internal
 */
class LocalhostIpcApp {
    static _initialized = false;
    static _ipc;
    static buildUrlForSocket(base, path = "ipc") {
        const url = new URL(base);
        url.protocol = "ws";
        url.pathname = [...url.pathname.split("/"), path].filter((v) => v).join("/");
        return url;
    }
    static async startup(opts) {
        if (!this._initialized) {
            core_common_1.IpcWebSocket.transport = new LocalTransport(opts);
            this._ipc = new core_common_1.IpcWebSocketFrontend();
            this._initialized = true;
        }
        await IpcApp_1.IpcApp.startup(this._ipc, opts);
        if (!core_common_1.IpcSession.active) {
            core_common_1.IpcSession.start(new LocalSession());
            IModelApp_1.IModelApp.onBeforeShutdown.addListener(() => core_common_1.IpcSession.stop());
        }
    }
}
exports.LocalhostIpcApp = LocalhostIpcApp;
//# sourceMappingURL=LocalhostIpcApp.js.map