var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import GitWorkspaceBackend from "./GitWorkspaceBackend";
import SparqlWorkspaceBackend from "./SparqlWorkspaceBackend";
import { GithubProviderClient } from "./GithubProviderClient";
import { GitlabProviderClient } from "./GitlabProviderClient";
import { BitbucketProviderClient } from "./BitbucketProviderClient";
import { GiteaProviderClient } from "./GiteaProviderClient";
import * as OAuth2Utils from "../../OAuth2Utils";
const registeredBackends = new Map();
export function registerWorkspaceBackend(workspaceId, backend) {
    registeredBackends.set(workspaceId, backend);
}
export function unregisterWorkspaceBackend(workspaceId) {
    registeredBackends.delete(workspaceId);
}
function base64Encode(value) {
    if (typeof globalThis.btoa === "function")
        return globalThis.btoa(value);
    const buf = globalThis.Buffer;
    if (buf && typeof buf.from === "function")
        return buf.from(value, "utf8").toString("base64");
    throw new Error("Base64 encoding not available in this environment");
}
function resolveSparqlAuthHeaders(persistentConfig, endpoint) {
    if (!persistentConfig)
        return undefined;
    const cfg = persistentConfig.getEndpointConfig(endpoint);
    const auth = cfg === null || cfg === void 0 ? void 0 : cfg.authentication;
    if (!auth)
        return undefined;
    if (auth.type === "basic") {
        const token = base64Encode(`${auth.username}:${auth.password}`);
        return { Authorization: `Basic ${token}` };
    }
    if (auth.type === "bearer") {
        return { Authorization: `Bearer ${auth.token}` };
    }
    if (auth.type === "apiKey") {
        return { [auth.headerName]: auth.apiKey };
    }
    if (auth.type === "oauth2") {
        const token = auth.accessToken || auth.idToken;
        if (!token)
            return undefined;
        return { Authorization: `Bearer ${token}` };
    }
    return undefined;
}
function resolveSparqlAuthHeadersWithRefresh(persistentConfig, endpoint) {
    return __awaiter(this, void 0, void 0, function* () {
        var _a;
        const cfg = persistentConfig.getEndpointConfig(endpoint);
        const auth = cfg === null || cfg === void 0 ? void 0 : cfg.authentication;
        if (!auth)
            return undefined;
        if (auth.type === "oauth2") {
            if (OAuth2Utils.isTokenExpired(auth.tokenExpiry)) {
                if (auth.refreshToken) {
                    try {
                        const tokenResponse = yield OAuth2Utils.refreshOAuth2Token({
                            clientId: auth.clientId,
                            tokenEndpoint: auth.tokenEndpoint,
                        }, auth.refreshToken);
                        const tokenExpiry = OAuth2Utils.calculateTokenExpiry(tokenResponse.expires_in);
                        persistentConfig.addOrUpdateEndpoint(endpoint, {
                            authentication: Object.assign(Object.assign({}, auth), { accessToken: tokenResponse.access_token, idToken: tokenResponse.id_token, refreshToken: tokenResponse.refresh_token || auth.refreshToken, tokenExpiry }),
                        });
                    }
                    catch (e) {
                        console.error("Failed to refresh OAuth2 token for endpoint", endpoint, e);
                    }
                }
            }
            const updated = (_a = persistentConfig.getEndpointConfig(endpoint)) === null || _a === void 0 ? void 0 : _a.authentication;
            if (updated && updated.type === "oauth2") {
                const token = updated.accessToken || updated.idToken;
                if (token)
                    return { Authorization: `Bearer ${token}` };
            }
            return undefined;
        }
        return resolveSparqlAuthHeaders(persistentConfig, endpoint);
    });
}
export function getWorkspaceBackend(config, options) {
    const registered = registeredBackends.get(config.id);
    if (registered)
        return registered;
    if (config.type === "git") {
        const client = (GithubProviderClient.canHandle(config) && new GithubProviderClient()) ||
            (GitlabProviderClient.canHandle(config) && new GitlabProviderClient()) ||
            (BitbucketProviderClient.canHandle(config) && new BitbucketProviderClient()) ||
            (GiteaProviderClient.canHandle(config) && new GiteaProviderClient()) ||
            undefined;
        return new GitWorkspaceBackend(config, client);
    }
    const persistentConfig = options === null || options === void 0 ? void 0 : options.persistentConfig;
    if (!persistentConfig) {
        const authHeaders = resolveSparqlAuthHeaders(undefined, config.endpoint);
        return new SparqlWorkspaceBackend(config, { authHeaders });
    }
    return new SparqlWorkspaceBackend(config, {
        getAuthHeaders: () => resolveSparqlAuthHeadersWithRefresh(persistentConfig, config.endpoint),
    });
}
//# sourceMappingURL=getWorkspaceBackend.js.map