class OneTimePasswordHandler {

    #baseUrl;
    #browserNotTerminatedError;

    constructor(baseUrl, browserNotTerminatedError) {
        this.#baseUrl = baseUrl;
        this.#browserNotTerminatedError = browserNotTerminatedError;
    }

    async appendTokenAndCallURLInExternalBrowser(url, target) {
        const otp = (await this.#fetchOtp())?.otp ?? null;
        OneTimePasswordHandler.#openContentInBrowser(url, target, otp);
    }

    async getOTPWithCallback(url, callback) {
        if (typeof callback !== "function") {
            console.error("Callback is not a function.");
            return false;
        }
        const otp = (await this.#fetchOtp())?.otp ?? null;
        callback(OneTimePasswordHandler.#extendUrlWithOtpIfPresent(url, otp));
    }

    async #fetchOtp() {
        return fetch(`${this.#baseUrl}/apis/`)
            .then(r => r.json())
            .then(({authentication: {_links: {create_publisher_otp: {url}}}}) => fetch(url))
            .then(OneTimePasswordHandler.#handleHTTPError)
            .catch(e => console?.log('One-time-password could not be retrieved.', e));
    }

    static #openContentInBrowser(url, target, otp = null) {
        url = OneTimePasswordHandler.#extendUrlWithOtpIfPresent(url, otp);
        url = OneTimePasswordHandler.#extendUrlWithAttribute(url, 'externalwindow', 'true');
        try {
            window.open(url, target);
        } catch (err) {
            // catch potential script errors and show error message; probably this will only happen in the QA with IE11
            // see http://stackoverflow.com/questions/34868680/internet-explorer-11-takes-excessively-long-to-shutdown
            alert(this.#browserNotTerminatedError); // trigger custom QA alert box
        }
    }

    static #extendUrlWithOtpIfPresent(url, otp) {
        if (otp !== null) {
            url = OneTimePasswordHandler.#extendUrlWithAttribute(url, 'otp', otp);
        }
        return url;
    }

    static #extendUrlWithAttribute(url, attribute, value) {
        const delimiter = url.includes('?') ? '&' : '?';
        url += `${delimiter}${attribute}=${value}`;
        return url;
    }

    static #handleHTTPError(response) {
        if (!response.ok) {
            throw new Error(response.statusText);
        }
        return response.json();
    }

}
