import '../../../../../@connectrpc_connect@1.6.1_@bufbuild_protobuf@1.10.1/node_modules/@connectrpc/connect/dist/esm/index.js';
import { LanguageServerService } from './api/proto/exa/language_server_pb/language_server_connect.js';
import '../../../../../@connectrpc_connect-web@1.6.1_@bufbuild_protobuf@1.10.1_@connectrpc_connect@1.6.1_@bufbuild_protobuf@1.10.1_/node_modules/@connectrpc/connect-web/dist/esm/index.js';
import { createConnectTransport } from '../../../../../@connectrpc_connect-web@1.6.1_@bufbuild_protobuf@1.10.1_@connectrpc_connect@1.6.1_@bufbuild_protobuf@1.10.1_/node_modules/@connectrpc/connect-web/dist/esm/connect-transport.js';
import { createPromiseClient } from '../../../../../@connectrpc_connect@1.6.1_@bufbuild_protobuf@1.10.1/node_modules/@connectrpc/connect/dist/esm/promise-client.js';

// This is the same as the monaco editor example
const transport = createConnectTransport({
    baseUrl: "https://web-backend.codeium.com",
    useBinaryFormat: true,
});
const client = createPromiseClient(LanguageServerService, transport);
let sessionId;
try {
    /**
     * Note that this won't be available in 'insecure contexts',
     * websites served under HTTP not HTTPS, but those are rare.
     * And it'll work in localhost for development.
     */
    sessionId = crypto.randomUUID();
}
catch {
    // When not in a secure context
    // https://stackoverflow.com/questions/105034/how-do-i-create-a-guid-uuid
    function uuidv4() {
        return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c => (+c ^ (crypto.getRandomValues(new Uint8Array(1))[0] ?? 0) & 15 >> +c / 4).toString(16));
    }
    sessionId = uuidv4();
}
async function getCodeiumCompletions({ text, cursorOffset, config, otherDocuments, }) {
    return (await client.getCompletions({
        metadata: {
            ideName: "web",
            ideVersion: "0.0.5",
            extensionName: "@valtown/codemirror-codeium",
            extensionVersion: "1.0.0",
            apiKey: config.apiKey,
            sessionId: sessionId,
            authSource: config.authSource,
        },
        document: {
            text: text,
            cursorOffset: BigInt(cursorOffset),
            language: config.language,
            // TODO: not sure why we have both language and
            // editorlanguage
            // The types don't like this here, but it works.
            editorLanguage: "typescript",
            lineEnding: "\n",
        },
        editorOptions: {
            tabSize: 2n,
            insertSpaces: true,
        },
        otherDocuments: otherDocuments,
        multilineConfig: undefined,
    }, {
        // signal,
        headers: {
            Authorization: `Basic ${config.apiKey}-${sessionId}`,
        },
    }));
}
/**
 * Make the body of the response a bit easier to work with:
 * turn a BigInt into an int in the response so that it can
 * be used with CodeMirror directly, and avoid using some
 * complex kinds of completions.
 */
function completionsToChangeSpec(completions) {
    return completions.completionItems.map((item) => {
        /**
         * Add absolute offsets for the suggestion text insertions
         * so that we can add matching decorations.
         */
        let combinedOffset = 0;
        return item.completionParts
            .filter((part) => {
            // Type 3 overwrites existing text. Maybe we need this eventually,
            // but not right now and it usually is duplicative.
            return part.type !== 3;
        })
            .map((part) => {
            const offset = Number(part.offset);
            const text = part.type === 2 ? `\n${part.text}` : part.text;
            const res = {
                absoluteStartPos: combinedOffset + offset,
                absoluteEndPos: combinedOffset + offset + text.length,
                from: offset,
                to: offset,
                insert: text,
            };
            combinedOffset += text.length;
            return res;
        });
    });
}

export { completionsToChangeSpec, getCodeiumCompletions };
