import ngModule from '../module';
const TOKEN_MULTIMEDIA = 'vnTokenMultimedia';
const TOKEN = 'vnToken';
/**
 * Saves and loads the token for the current logged in user.
 *
 * @property {String} token The current login token or %null
 */
export default class Token {
    constructor(vnInterceptor, $http, $rootScope) {
        Object.assign(this, {
            vnInterceptor,
            $http,
            $rootScope
        });

        try {
            this.getStorage(sessionStorage);
            this.remember = true;

            if (!this.token) {
                this.getStorage(localStorage);
                this.remember = false;
            }
        } catch (e) {}
    }

    set(token, tokenMultimedia, created, ttl, remember) {
        this.unset();

        Object.assign(this, {
            token,
            tokenMultimedia,
            created,
            ttl,
            remember
        });
        this.vnInterceptor.setToken(token, tokenMultimedia);
        try {
            if (remember)
                this.setStorage(localStorage, token, tokenMultimedia, created, ttl);
            else
                this.setStorage(sessionStorage, token, tokenMultimedia, created, ttl);
        } catch (err) {
            console.error(err);
        }
    }

    unset() {
        this.token = null;
        this.tokenMultimedia = null;
        this.created = null;
        this.ttl = null;
        this.remember = null;
        this.vnInterceptor.setToken(null);

        this.removeStorage(localStorage);
        this.removeStorage(sessionStorage);
    }

    getStorage(storage) {
        this.token = storage.getItem(TOKEN);
        this.tokenMultimedia = storage.getItem(TOKEN_MULTIMEDIA);
        if (!this.token) return;
        const created = storage.getItem('vnTokenCreated');
        this.created = created && new Date(created);
        this.ttl = storage.getItem('vnTokenTtl');
    }

    setStorage(storage, token, tokenMultimedia, created, ttl) {
        storage.setItem(TOKEN_MULTIMEDIA, tokenMultimedia);
        storage.setItem(TOKEN, token);
        storage.setItem('vnTokenCreated', created.toJSON());
        storage.setItem('vnTokenTtl', ttl);
    }

    removeStorage(storage) {
        storage.removeItem(TOKEN);
        storage.removeItem(TOKEN_MULTIMEDIA);
        storage.removeItem('vnTokenCreated');
        storage.removeItem('vnTokenTtl');
    }

    fetchConfig() {
        const filter = {fields: ['renewInterval', 'renewPeriod']};
        this.$http.get('AccessTokenConfigs/findOne', {filter}).then(res => {
            const data = res.data;
            if (!data) return;
            this.renewPeriod = data.renewPeriod;
            this.stopRenewer();
            this.intervalId = setInterval(() => this.checkValidity(), data.renewInterval * 1000);
        });
    }

    checkValidity() {
        if (this.checking || !this.created) return;
        this.checking = true;
        const renewPeriod = Math.min(this.ttl, this.renewPeriod) * 1000;
        const maxDate = this.created.getTime() + renewPeriod;
        const now = new Date().getTime();

        if (now <= maxDate) {
            this.checking = false;
            return;
        }

        this.$http.post('VnUsers/renewToken')
            .then(res => {
                const token = res.data;
                const tokenMultimedia =
                    localStorage.getItem(TOKEN_MULTIMEDIA)
                    ?? sessionStorage.getItem(TOKEN_MULTIMEDIA);

                return this.$http.post('VnUsers/renewToken', null, {
                    headers: {Authorization: tokenMultimedia}
                })
                    .then(({data}) => {
                        const tokenMultimedia = data;
                        this.set(token.id, tokenMultimedia.id, new Date(), token.ttl, this.remember);
                    });
            })
            .finally(() => {
                this.checking = false;
            });
    }

    stopRenewer() {
        clearInterval(this.intervalId);
    }
}
Token.$inject = ['vnInterceptor', '$http', '$rootScope'];

ngModule.service(TOKEN, Token);