Source: widget/help/Cookie.js

(function() {
    /**
     * @typedef {Object} Help4.widget.help.Cookie.Params
     * @property {boolean} [session = false]
     * @property {string} type
     * @property {string} [key]
     */

    /**
     * @typedef {Object} Help4.widget.help.Cookie.PageCookieInformation
     * @property {Help4.service.StorageService} storageService
     * @property {Object} storageTarget
     * @property {Object} data
     * @property {*} typeData
     * @property {string} key
     * @property {boolean} keyContained
     */

    /**
     * {@link Help4.controller.Controller#getPageCookie}
     * {@link Help4.controller.Controller#setPageCookie}
     * {@link Help4.controller.Controller#remPageCookie}
     * Cookie manager for CMP4 help widget
     */
    Help4.widget.help.Cookie = class {
        /**
         * @param {Help4.widget.help.Widget} widget
         * @param {Help4.widget.help.Cookie.Params} params
         * @returns {Promise<boolean>}
         */
        static async getPageCookie(widget, params) {
            const info = await this.#getPageCookieInformation(widget, params);
            return info.keyContained;
        }

        /**
         * @param {Help4.widget.help.Widget} widget
         * @param {Help4.widget.help.Cookie.Params} params
         * @returns {Promise<void>}
         */
        static async setPageCookie(widget, params) {
            const {
                storageService,
                storageTarget,
                data,
                typeData,
                key,
                keyContained
            } = await this.#getPageCookieInformation(widget, params);

            // add only if not already in
            if (keyContained) return;

            const store = typeData || (data[params.type] = []);
            store.push(key);

            const {SERIALIZE_PAGE_KEY, JSON} = Help4;
            await storageService.set(
                SERIALIZE_PAGE_KEY,
                JSON.stringify(data),
                storageTarget
            );
        }

        /**
         * @param {Help4.widget.help.Widget} widget
         * @param {Help4.widget.help.Cookie.Params} params
         * @returns {Promise<void>}
         */
        static async remPageCookie(widget, params) {
            const {
                storageService,
                storageTarget,
                data,
                typeData,
                key,
                keyContained
            } = await this.#getPageCookieInformation(widget, params);

            // data not included; no need to remove
            if (!keyContained) return;

            typeData.splice(typeData.indexOf(key), 1);

            const {SERIALIZE_PAGE_KEY, JSON} = Help4;
            await storageService.set(
                SERIALIZE_PAGE_KEY,
                JSON.stringify(data),
                storageTarget
            );
        }

        /**
         * @private
         * @param {Help4.widget.help.Widget} widget
         * @param {Help4.widget.help.Cookie.Params} params
         * @returns {Promise<Help4.widget.help.Cookie.PageCookieInformation>}
         */
        static async #getPageCookieInformation(widget, {session = false, type, key}) {
            const {
                SERIALIZE_PAGE_KEY, COOKIE_KEYS, JSON,
                service: {StorageService: {STORAGE_ID}}
            } = Help4;

            const {
                controller,
                configuration: {core},
                widget: {help: {data}}
            } = widget.getContext();
            const storageService = controller.getService('storage');
            const storageTarget = session ? {target: STORAGE_ID.session} : {exclude: STORAGE_ID.session};

            const helpPromise = data.getHelp();
            const cookiePromise = storageService.get(SERIALIZE_PAGE_KEY, storageTarget);
            let [help, cookie] = await Help4.Promise.all([helpPromise, cookiePromise]);

            const {product, system, screenId} = core;
            const {version} = help.filter(({_catalogueType}) => Help4.includes(['UACP', 'SEN', 'SEN2'], _catalogueType))[0] || core;
            const id = [product || '', version || '', system || '', screenId].join('#') + (key ? `#${key}` : '');

            const getDefaultData = () => Object.values(COOKIE_KEYS).reduce((result, value) => (result[value] = []) && result, {});
            try {
                cookie = cookie && JSON.parse(cookie) || getDefaultData();
                if (typeof cookie === 'string' || Help4.isArray(cookie)) cookie = getDefaultData();
            } catch (e) {
                cookie = getDefaultData();
            }

            const typeData = cookie[type];

            return {
                storageService,
                storageTarget,
                data: cookie,
                typeData,
                key: id,
                keyContained: typeData ? typeData.indexOf(id) >= 0 : false
            }
        }
    }
})();