import * as did from "../did/index.js";
import { setup } from "../setup/internal.js";
import { LinkingError } from "./linking.js";
export const createWssChannel = async (options) => {
    const { username, handleMessage } = options;
    const rootDid = await waitForRootDid(username);
    if (!rootDid) {
        throw new LinkingError(`Failed to lookup DID for ${username}`);
    }
    const apiEndpoint = setup.getApiEndpoint();
    const endpoint = apiEndpoint.replace(/^https?:\/\//, "wss://");
    const topic = `deviceLink#${rootDid}`;
    console.log("Opening channel", topic);
    const socket = new WebSocket(`${endpoint}/user/link/${rootDid}`);
    await waitForOpenConnection(socket);
    socket.onmessage = handleMessage;
    const send = publishOnWssChannel(socket);
    const close = closeWssChannel(socket);
    return {
        send,
        close
    };
};
const waitForRootDid = async (username) => {
    let rootDid = await did.root(username);
    if (rootDid) {
        return rootDid;
    }
    return new Promise((resolve) => {
        const maxRetries = 3;
        let tries = 0;
        const rootDidInterval = setInterval(async () => {
            console.log("Could not fetch root DID. Retrying");
            rootDid = await did.root(username).catch((e) => {
                clearInterval(rootDidInterval);
                throw e;
            });
            if (!rootDid && tries < maxRetries) {
                tries++;
                return;
            }
            clearInterval(rootDidInterval);
            resolve(rootDid);
        }, 2000);
    });
};
const waitForOpenConnection = async (socket) => {
    return new Promise((resolve, reject) => {
        socket.onopen = () => {
            resolve();
        };
        socket.onerror = () => {
            reject("Websocket channel could not be opened");
        };
    });
};
export const closeWssChannel = (socket) => {
    return function () {
        if (socket) {
            socket.close(1000);
        }
    };
};
export const publishOnWssChannel = (socket) => {
    return function (data) {
        const binary = typeof data === "string"
            ? new TextEncoder().encode(data).buffer
            : data;
        socket?.send(binary);
    };
};
//# sourceMappingURL=channel.js.map