// Copyright (c) 2009-2026 SAP SE, All Rights Reserved

/**
 * @file This is Notifications module that loads the Notifications component. And also creates a notification button if the ShellHeader is used.
 */
sap.ui.define([
    "sap/ui/Device",
    "sap/ui/core/Component",
    "sap/ushell/Config",
    "sap/ushell/Container",
    "sap/ushell/EventHub",
    "sap/ushell/modules/Notifications/NotificationsProvider",
    "sap/ushell/resources",
    "sap/ushell/state/ShellModel",
    "sap/ushell/ui/shell/ShellHeadItem",
    "sap/ushell/library"
], (
    Device,
    Component,
    Config,
    Container,
    EventHub,
    NotificationsProvider,
    ushellResources,
    ShellModel,
    ShellHeadItem,
    ushellLibrary
) => {
    "use strict";

    async function getRendererInternalAsync (sRendererName) {
        return new Promise(async (resolve) => {
            const oRenderer = Container.getRendererInternal(sRendererName);
            if (oRenderer) {
                resolve(oRenderer);
            } else {
                Container.attachRendererCreatedEvent(function onRendererCreated () {
                    Container.detachRendererCreatedEvent(onRendererCreated);
                    resolve(Container.getRendererInternal(sRendererName));
                });
            }
        });
    }

    /**
     * Default Notifications component for the Fiori Launchpad.
     *
     * @augments sap.ushell.modules.Notifications.NotificationsProvider
     * @since 1.142.0
     * @private
     */
    class NotificationsModule extends NotificationsProvider {
        /**
         * The promise that resolves when the component is created.
         *
         * @type {Promise<sap.ui.core.Component>}
         * @since 1.142.0
         * @private
         */
        #pComponent;

        /**
         * The promise that resolves when the notification button is created.
         *
         * @type {Promise}
         * @since 1.142.0
         * @private
         */
        #pNotificationButton;

        /**
         * Loads the notifications component and initializes the notifications functionality.
         *
         * @param {sap.ushell.modules.Notifications.NotificationsAPI} oNotificationsAPI The side navigation API object.
         *
         * @since 1.142.0
         * @private
         */
        constructor (oNotificationsAPI) {
            super(oNotificationsAPI);
            this.#init(oNotificationsAPI);
        }

        async #init (oNotificationsAPI) {
            await getRendererInternalAsync();
            const oConfigModel = ShellModel.getConfigModel();
            // create the notification button for ShellHeader only.
            this.#pNotificationButton = this.#createNotificationButton();
            this.#pNotificationButton.then(() => {
                oNotificationsAPI.bindNotificationsCount("/notificationsCount", oConfigModel);
                oNotificationsAPI.attachNotificationsPress(() => {
                    EventHub.emit("showNotifications", Date.now());
                });
            });

            this.#pComponent = Component.create({
                name: "sap.ushell.components.shell.Notifications",
                manifest: false,
                componentData: {
                    notificationsAPI: oNotificationsAPI
                }
            });
        }

        /**
         * Returns a promise that resolves when the module is initialized.
         * Used for testing purposes.
         *
         * @returns {Promise} A promise that resolves when the module is initialized.
         * @since 1.142.0
         * @private
         */
        async initialized () {
            return Promise.all([this.#pNotificationButton, this.#pComponent]);
        }

        /**
         * Cleans up the component instance.
         *
         * @returns {Promise} A promise that resolves when the component is destroyed.
         * @since 1.142.0
         * @private
         * @override
         */
        async exit () {
            (await this.#pComponent).exit();
            (await this.#pNotificationButton)?.destroy();
        }

        /**
         * Creates the notification button and adds it to the ShellHeader.
         * This is only required for compatibility reasons. Once the ShellHeader is removed, this can be removed.
         *
         * @returns {Promise} A promise that resolves when the button is created.
         * @since 1.142.0
         * @private
         */
        async #createNotificationButton () {
            if (Config.last("/core/shellBar/enabled")) {
                return;
            }

            const FloatingNumberType = ushellLibrary.FloatingNumberType;

            // The press handler is added in the Notification Component
            const oNotificationToggleButton = new ShellHeadItem({
                id: "NotificationsCountButton",
                tooltip: ushellResources.i18n.getText("notificationsBtn_title"),
                icon: "sap-icon://bell",
                text: ushellResources.i18n.getText("notificationsBtn_title"),
                ariaLabel: ushellResources.i18n.getText("notificationsBtn_title"),
                ariaHaspopup: "dialog",
                enabled: true,
                selected: false,
                floatingNumberMaxValue: Device.system.phone ? 99 : 999, // according to the UX specification
                floatingNumberType: FloatingNumberType.Notifications
            });
            oNotificationToggleButton.setModel(ushellResources.i18nModel, "i18n");

            const FrameBoundExtension = await Container.getServiceAsync("FrameBoundExtension");
            const oHeaderItem = await FrameBoundExtension.createHeaderItem({
                id: oNotificationToggleButton.getId()
            });
            oHeaderItem.showOnHome();
            oHeaderItem.showForAllApps();
            return oNotificationToggleButton;
        }
    }
    return NotificationsModule;
}, false);
