import * as Comlink from 'comlink';
import { LanguageServerClient, languageServerWithClient } from "@marimo-team/codemirror-languageserver";
import MessagePortTransport from "../rpc/transport";
import { HighlightStyle } from "@codemirror/language";
import { languageSupportCompartment, renderMarkdownCode } from "../editor";
import markdownit from 'markdown-it';
import { vscodeLightDark } from "../themes/vscode";
const clients = new Map();
// TODO: better fix for this reference sticking around to prevent Comlink from releasing the port
export const languageServerFactory = new Map();
export const lspWorkers = new Map();
export var LSP;
(function (LSP) {
    async function worker(language, fs) {
        let factory, worker;
        console.debug('language', { language });
        switch (language) {
            case 'javascript':
            case 'typescript':
                factory = languageServerFactory.get('javascript');
                worker = lspWorkers.get('javascript');
                console.debug('got worker', { worker, factory });
                if (!factory) {
                    worker = new SharedWorker(new URL('../workers/javascript.worker.js', import.meta.url), { type: 'module' });
                    worker.port.start();
                    lspWorkers.set('javascript', worker);
                    const { createLanguageServer } = Comlink.wrap(worker.port);
                    factory = createLanguageServer;
                    languageServerFactory.set('javascript', factory);
                }
                break;
        }
        await factory?.(Comlink.proxy({ fs }));
        return { worker };
    }
    LSP.worker = worker;
    async function client({ fs, language, path, view }) {
        let client = clients.get(language);
        let clientExtension;
        const uri = `file:///${path}`;
        if (!client) {
            const { worker } = await LSP.worker(language, fs);
            if (!worker)
                return null;
            console.debug('got worker', { worker });
            client = new LanguageServerClient({
                transport: new MessagePortTransport(worker.port),
                rootUri: 'file:///',
                workspaceFolders: [{ name: 'workspace', uri: 'file:///' }]
            });
        }
        clients.set(language, client);
        clientExtension = { client, extension: [] };
        clientExtension.extension = languageServerWithClient({
            client: clientExtension.client,
            documentUri: uri,
            languageId: language,
            allowHTMLContent: true,
            markdownRenderer(markdown) {
                const support = languageSupportCompartment.get(view.state);
                const highlighter = vscodeLightDark[1].find(item => item.value instanceof HighlightStyle)?.value;
                const parser = support.language?.parser;
                const md = markdownit({
                    highlight: (str) => {
                        return renderMarkdownCode(str, parser, highlighter);
                    }
                });
                return md.render(markdown);
            },
        });
        return clientExtension;
    }
    LSP.client = client;
})(LSP || (LSP = {}));
