import { ProviderError } from "./providers.js";
export class OffscreenCaptionTranslator {
    tabId;
    send;
    sequence = 0;
    constructor(tabId, send = runtimeSend) {
        this.tabId = tabId;
        this.send = send;
    }
    async availability(_sourceLanguage, _targetLanguage) {
        const result = await this.send({ type: "m1.offscreen.translation.availability" });
        if (!record(result) || (result.status !== "available" && result.status !== "unavailable" && result.status !== "unconfigured" && result.status !== "corrupt"))
            return "unavailable";
        return result.status;
    }
    async prepare(sourceLanguage, _targetLanguage) {
        const result = await this.send({ type: "m1.offscreen.translation.prepare", sourceLanguage });
        if (!record(result) || result.ok !== true)
            throw new ProviderError(translationFailure(record(result) ? result.error : undefined));
    }
    async translate(text, sourceLanguage, _targetLanguage, signal, priority = "automatic", context) {
        if (signal.aborted)
            throw new ProviderError("cancelled");
        const requestId = `${this.tabId}:${++this.sequence}`;
        const cancel = () => { void this.send({ type: "m1.offscreen.translation.cancel", requestId }).catch(() => undefined); };
        signal.addEventListener("abort", cancel, { once: true });
        try {
            const result = await this.send({ type: "m1.offscreen.translation.translate", requestId, tabId: this.tabId, text, sourceLanguage, priority, ...(context ? { cueId: context.cueId, sourceRevision: context.sourceRevision, sessionId: context.sessionId } : {}) });
            if (signal.aborted)
                throw new ProviderError("cancelled");
            if (!record(result) || result.ok !== true || typeof result.text !== "string")
                throw new ProviderError(translationFailure(record(result) ? result.error : undefined));
            if (context && (!record(result.context) || !sameContext(result.context, context)))
                throw new ProviderError("cancelled");
            return result.text;
        }
        finally {
            signal.removeEventListener("abort", cancel);
        }
    }
}
function translationFailure(value) {
    return value === "translator_unavailable" || value === "translator_unconfigured" || value === "translator_overloaded" || value === "translator_failed" || value === "translator_load_failed" || value === "translator_cache_corrupt" || value === "translator_inference_failed" || value === "translator_output_invalid" || value === "language_unsupported" || value === "cancelled" ? value : "translator_failed";
}
function runtimeSend(message) {
    const extension = globalThis;
    return extension.chrome?.runtime?.sendMessage ? extension.chrome.runtime.sendMessage(message) : Promise.reject(new Error("extension_runtime_unavailable"));
}
function record(value) { return typeof value === "object" && value !== null; }
function sameContext(value, expected) {
    return value.cueId === expected.cueId && value.sourceRevision === expected.sourceRevision && value.sessionId === expected.sessionId;
}
