"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GetSslCertificate = void 0;
const AbortedError_1 = require("../../../base/lib/util/AbortedError");
const Drop_1 = require("../../../base/lib/util/Drop");
class GetSslCertificate {
    constructor(effects, hostnames, algorithm) {
        this.effects = effects;
        this.hostnames = hostnames;
        this.algorithm = algorithm;
    }
    /**
     * Returns the an SSL Certificate for the given hostnames if permitted. Restarts the service if it changes
     */
    const() {
        return this.effects.getSslCertificate({
            hostnames: this.hostnames,
            algorithm: this.algorithm,
            callback: this.effects.constRetry &&
                (() => this.effects.constRetry && this.effects.constRetry()),
        });
    }
    /**
     * Returns the an SSL Certificate for the given hostnames if permitted. Does nothing if it changes
     */
    once() {
        return this.effects.getSslCertificate({
            hostnames: this.hostnames,
            algorithm: this.algorithm,
        });
    }
    async *watchGen(abort) {
        const resolveCell = { resolve: () => { } };
        this.effects.onLeaveContext(() => {
            resolveCell.resolve();
        });
        abort?.addEventListener('abort', () => resolveCell.resolve());
        while (this.effects.isInContext && !abort?.aborted) {
            let callback = () => { };
            const waitForNext = new Promise((resolve) => {
                callback = resolve;
                resolveCell.resolve = resolve;
            });
            yield await this.effects.getSslCertificate({
                hostnames: this.hostnames,
                algorithm: this.algorithm,
                callback: () => callback(),
            });
            await waitForNext;
        }
        return new Promise((_, rej) => rej(new AbortedError_1.AbortedError()));
    }
    /**
     * Watches the SSL Certificate for the given hostnames if permitted. Returns an async iterator that yields whenever the value changes
     */
    watch(abort) {
        const ctrl = new AbortController();
        abort?.addEventListener('abort', () => ctrl.abort());
        return Drop_1.DropGenerator.of(this.watchGen(ctrl.signal), () => ctrl.abort());
    }
    /**
     * Watches the SSL Certificate for the given hostnames if permitted. Takes a custom callback function to run whenever it changes
     */
    onChange(callback) {
        ;
        (async () => {
            const ctrl = new AbortController();
            for await (const value of this.watch(ctrl.signal)) {
                try {
                    const res = await callback(value);
                    if (res.cancel) {
                        ctrl.abort();
                        break;
                    }
                }
                catch (e) {
                    console.error('callback function threw an error @ GetSslCertificate.onChange', e);
                }
            }
        })()
            .catch((e) => callback(null, e))
            .catch((e) => console.error('callback function threw an error @ GetSslCertificate.onChange', e));
    }
    /**
     * Watches the SSL Certificate for the given hostnames if permitted. Returns when the predicate is true
     */
    waitFor(pred) {
        const ctrl = new AbortController();
        return Drop_1.DropPromise.of(Promise.resolve().then(async () => {
            for await (const next of this.watchGen(ctrl.signal)) {
                if (pred(next)) {
                    return next;
                }
            }
            return null;
        }), () => ctrl.abort());
    }
}
exports.GetSslCertificate = GetSslCertificate;
//# sourceMappingURL=GetSslCertificate.js.map