class MarketWebLoginManager {
    eventTarget = window ?? document?.body;
    endpoint = '';
    storagePrefix = 'pn-user';
    checkUserLoggedInStateInterval = 0;
    baseUrls = {
        at: 'https://atportal.postnord.com/api/unified-login/backend',
        prod: 'https://portal.postnord.com/api/unified-login/backend',
    };
    events = {
        loginstatechange: 'loginstatechange',
    };
    endpoints = {
        authorizationEndpoint: `/authorization`,
        tokenExchangeEndpoint: `/token`,
        userInfoEndpoint: `/user`,
        logoutEndpoint: `/logout`,
    };
    keys = {
        tokensource: 'tokensource',
        token: 'token',
        accessToken: 'accessToken',
        user: 'user',
        expire: 'expire',
        expireDate: 'expiredate',
    };
    overridetokenValue = 'overridetokenValue';
    siteUrl = window.location.origin;
    abortSignalForLoginCheck = null;
    loginCheckInProgress = false;
    loginCheckTimer = null;
    constructor(options = null) {
        if (!options) {
            return;
        }
        this.eventTarget = options.eventTarget ? options.eventTarget : this.eventTarget;
        this.endpoint = options.endpoint ? options.endpoint : `${window.location.protocol}//${window.location.host}`;
        this.storagePrefix ??= options.storagePrefix;
        this.checkUserLoggedInStateInterval =
            options.checkUserLoggedInStateInterval && options.checkUserLoggedInStateInterval > 0 ? parseInt(options.checkUserLoggedInStateInterval + '', 10) : 0;
        if (options.userInfo) {
            this.store.set(this.keys.user, options.userInfo);
            this.registerToken(this.overridetokenValue, 'override');
        }
    }
    init(checkParameters = true) {
        if (checkParameters) {
            this.checkParameters();
            this.checkPNTopbar();
            this.checkExpireTime();
            if (this.store.get(this.keys.token) && !this.store.get(this.keys.user)) {
                this.fetchUserInfo();
            }
            this.loginStateChange();
            if (this.checkUserLoggedInStateInterval > 0) {
                this.initiateLoggedInCheck();
            }
        }
    }
    setSiteUrl(siteUrl) {
        if (siteUrl) {
            this.siteUrl = siteUrl;
        }
    }
    initiateLoggedInCheck() {
        if (this.isLoggedIn()) {
            if (window && window['AbortController']) {
                this.abortSignalForLoginCheck = new AbortController();
            }
            this.loginCheckTimer = window.setInterval(() => {
                this.doExternalLoggedInCheck()
                    .then(() => { })
                    .catch(() => { });
            }, this.checkUserLoggedInStateInterval);
        }
    }
    async doExternalLoggedInCheck() {
        if (!window.navigator.onLine) {
            // Don't check if the user is not online
            return;
        }
        if (!this.getToken()) {
            window.clearInterval(this.checkUserLoggedInStateInterval);
            return;
        }
        if (this.loginCheckInProgress && this.abortSignalForLoginCheck) {
            this.abortSignalForLoginCheck.abort();
            this.abortSignalForLoginCheck = new AbortController();
        }
        this.loginCheckInProgress = true;
        const reqConfig = {
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': this.getToken(),
            },
        };
        if (this.abortSignalForLoginCheck && this.abortSignalForLoginCheck['signal']) {
            reqConfig['signal'] = this.abortSignalForLoginCheck['signal'];
        }
        const response = await fetch(`${this.getBaseUrl()}${this.endpoints.userInfoEndpoint}`, reqConfig);
        if (response.status === 409) {
            // This is a status the API returns if a user has been logged out
            window.clearInterval(this.checkUserLoggedInStateInterval);
            console.log('Cleared out user data due to bad response from authentication endpoint');
            this.LogoutUser();
            return;
        }
        if (!response.ok) {
            // The response was "bad". This could be due to bad connectivity or something else.
            // We'll ignore it so we don't unecessarily log users out or have them loose state if they're switching connection
            return;
        }
        const data = await response.json();
        if (!data || !data['accessToken']) {
            window.clearInterval(this.checkUserLoggedInStateInterval);
            console.log('Cleared out user data due to bad response from authentication endpoint');
            this.LogoutUser();
        }
        this.loginCheckInProgress = false;
    }
    LogoutUser() {
        this.clearUserData();
        // Log out user
        if (this.eventTarget) {
            const logoutLink = this.eventTarget.querySelector('#pn-marketweb-header-logoutlink');
            if (logoutLink) {
                logoutLink.click();
                return;
            }
        }
        this.loginStateChange();
        // If no logout link was found, attempt to change URL to redirect link
        const currentPageHref = window.location.href;
        window.location.href = this.getLogoutUrl(currentPageHref);
    }
    isLoggedIn(override = false) {
        if (override) {
            return override;
        }
        let isLoggedIn = this.store.get(this.keys.token) && this.store.get(this.keys.user) ? true : false;
        if (!isLoggedIn && this.store.get(this.keys.token) === this.overridetokenValue) {
            isLoggedIn = true;
        }
        return isLoggedIn;
    }
    registerToken(token = '', tokenSource = 'frontend') {
        if (!token || token === this.getToken()) {
            return;
        }
        this.clearUserData();
        this.store.set(this.keys.tokensource, tokenSource);
        this.store.set(this.keys.token, token);
        this.fetchUserInfo();
    }
    invalidateTokenOfType(tokenSource = 'frontend') {
        const currentToken = this.store.get(this.keys.token);
        if (!currentToken) {
            return;
        }
        const currentTokenSource = this.store.get(this.keys.tokensource);
        if (currentTokenSource !== tokenSource) {
            return;
        }
        // If we have a token and the source is set then we will invalidate the user data
        this.clearUserData();
    }
    getLoginUrl(redirectPage = '') {
        const currentPage = window.location.href;
        redirectPage = redirectPage ? redirectPage : currentPage;
        return `${this.getBaseUrl()}${this.endpoints.authorizationEndpoint}?redirectionUrl=${redirectPage}`;
    }
    getLogoutUrl(linkHref = '') {
        if (linkHref.indexOf('logout?logoutUrl') !== -1) {
            // Link has already been formatted.
            return linkHref;
        }
        let redirectPage = linkHref
            .replace('logout', '')
            .replace('http://window.location.href/?', window.location.href)
            .replace('https://window.location.href/?', window.location.href);
        let rootUrl = this.siteUrl;
        try {
            const url = new URL(this.siteUrl + '');
            rootUrl = url.origin;
        }
        catch (e) { }
        const addSlash = rootUrl.lastIndexOf('/') !== rootUrl.length - 1;
        const siteUrl = rootUrl + (addSlash ? '/' : '') + 'logout';
        const secondLogoutUrl = `${this.getBaseUrl()}${this.endpoints.logoutEndpoint}?authorization=${this.store.get(this.keys.token)}%26redirectionUrl=${redirectPage}`;
        const logoutUrl = `${siteUrl}?logoutUrl=${secondLogoutUrl}`;
        return logoutUrl;
    }
    getUserInfo() {
        if (this.isLoggedIn()) {
            return this.store.get(this.keys.user);
        }
    }
    getEventTarget() {
        return this.eventTarget;
    }
    checkExpireTime() {
        const expire = this.store.get(this.keys.expire);
        if (!expire) {
            return;
        }
        const now = new Date();
        const expireDate = new Date(Math.floor(parseInt(expire, 10) * 1000));
        if (now > expireDate) {
            console.info('Login time has expired');
            this.clearUserData();
            this.loginStateChange();
        }
    }
    checkPNTopbar() {
        if (this.isLoggedIn() || !window['pnTopbar'] || !window['pnTopbar']['session_id']) {
            return;
        }
        this.store.set(this.keys.token, window['pnTopbar']['session_id']);
        this.fetchUserInfo();
    }
    checkParameters() {
        if (!window?.location) {
            return;
        }
        const params = new URLSearchParams(window.location.search);
        if (params.get('oneTimeCode')) {
            const oneTimeCode = params.get('oneTimeCode');
            this.exchangeToken(oneTimeCode).then(() => {
                const currentHref = window.location.href;
                const paramPrefix = currentHref.indexOf('?oneTimeCode') !== -1 ? '?' : '&';
                const newUrl = currentHref.replace(`${paramPrefix}oneTimeCode=${oneTimeCode}`, '');
                history.replaceState({}, document.querySelector('title').innerText, newUrl);
            });
        }
    }
    async fetchUserInfo() {
        const token = this.store.get(this.keys.token);
        if (this.store.get(this.keys.token) === this.overridetokenValue) {
            console.info('Did not fetch user data since it was set by an override');
            return;
        }
        const reqConfig = {
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': token,
            },
        };
        const response = await fetch(`${this.getBaseUrl()}${this.endpoints.userInfoEndpoint}`, reqConfig);
        const data = await response.json();
        if (data && data['idToken']) {
            try {
                const { idToken, expiryTime, accessToken } = data;
                const userInfo = this.parseUserInfo(idToken);
                if (!userInfo) {
                    console.error('Userdata is not valid');
                    this.clearUserData();
                    return;
                }
                this.store.set(this.keys.user, userInfo);
                // 10 Min early expire
                this.store.set(this.keys.accessToken, accessToken);
                this.store.set(this.keys.expire, expiryTime);
                this.store.set(this.keys.expireDate, new Date(Math.floor(parseInt(expiryTime, 10) * 1000)));
                this.loginStateChange();
            }
            catch (e) {
                console.error('Unable to get user information', e);
            }
        }
        else {
            console.error('Unable to get user information. Clearing login state');
            this.clearUserData();
        }
    }
    clearUserData() {
        this.store.remove(this.keys.user);
        this.store.remove(this.keys.tokensource);
        this.store.remove(this.keys.accessToken);
        this.store.remove(this.keys.token);
        this.store.remove(this.keys.expire);
        this.store.remove(this.keys.expireDate);
    }
    getToken() {
        return this.store.get(this.keys.token);
    }
    getAccessToken() {
        return this.store.get(this.keys.accessToken);
    }
    async exchangeToken(oneTimeCode) {
        this.clearUserData();
        const response = await fetch(`${this.getBaseUrl()}${this.endpoints.tokenExchangeEndpoint}?oneTimeCode=${oneTimeCode}`);
        const { token } = await response.json();
        if (typeof token === 'string' && token) {
            this.store.set(this.keys.token, token);
        }
        this.fetchUserInfo();
    }
    loginStateChange() {
        if (!this.eventTarget) {
            return;
        }
        this.eventTarget.dispatchEvent(new CustomEvent(this.events.loginstatechange, {
            detail: this.isLoggedIn(),
        }));
    }
    getBaseUrl() {
        const atEnvironments = ['localhost', 'integration.', 'inte.', 'local.', 'prep.'];
        let useATEnv = atEnvironments.filter(x => this.endpoint.indexOf(x) !== -1).length > 0;
        if (['devportal.postnord.com', 'atportal.postnord.com'].indexOf(window.location.hostname) !== -1) {
            useATEnv = true;
        }
        if (useATEnv) {
            return this.baseUrls.at;
        }
        return this.baseUrls.prod;
    }
    parseUserInfo(idToken) {
        if (!idToken) {
            return null;
        }
        var base64Url = idToken.split('.')[1];
        var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
        var jsonPayload = decodeURIComponent(atob(base64)
            .split('')
            .map(function (c) {
            return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
        })
            .join(''));
        return JSON.parse(jsonPayload);
    }
    store = {
        get: (key) => {
            const value = window.localStorage.getItem(`${this.storagePrefix}-${key}`);
            if (!value) {
                return value;
            }
            if (value.indexOf('{') === 0) {
                try {
                    return JSON.parse(value);
                }
                catch (e) { }
            }
            if (value.indexOf(',') !== -1) {
                return value.split(',');
            }
            return value;
        },
        set: (key, value) => {
            if (typeof value === 'object' && typeof value.length === 'undefined') {
                window.localStorage.setItem(`${this.storagePrefix}-${key}`, JSON.stringify(value));
                return;
            }
            window.localStorage.setItem(`${this.storagePrefix}-${key}`, value);
        },
        remove: (key) => {
            window.localStorage.removeItem(`${this.storagePrefix}-${key}`);
        },
    };
}
export { MarketWebLoginManager };
//# sourceMappingURL=MarketWebLoginManager.js.map
