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

sap.ui.define([
    "sap/ui/core/Element",
    "sap/ushell/modules/BaseAPI",
    "sap/ushell/state/StateManager"
], (
    Element,
    BaseAPI,
    StateManager
) => {
    "use strict";

    // shortcut for sap.ushell.state.StateManager.Operation
    const Operation = StateManager.Operation;

    /**
     * @alias sap.ushell.modules.Notifications.NotificationsAPI
     * @namespace
     * @description The API object for the Notifications module.
     * This module cannot be required it gets injected in the constructor of the Notifications module.
     * @see sap.ushell.modules.Notifications.Notifications
     *
     * @hideconstructor
     *
     * @since 1.142.0
     * @private
     * @ui5-restricted ANS
     */
    class NotificationsAPI extends BaseAPI {
        /**
         * The instance of the ShellBar or ShellHeader depending on the ushell Config.
         *
         * @type {sap.f.gen.ui5.webcomponents_fiori.dist.ShellBar|sap.ushell.ui.ShellHeader}
         * @since 1.142.0
         * @private
         */
        #oShellBar;

        /**
         * Creates a new instance of the NotificationsAPI.
         *
         * @param {object} oConfig The configuration object for the notifications module.
         * @since 1.142.0
         * @private
         * @ui5-restricted ANS
         */
        constructor (oConfig) {
            super(oConfig);
            this.#oShellBar = Element.getElementById("shell-header")?.getComponentInstance?.()?.getRootControl()?.byId("shellBar");
            if (!this.#oShellBar) {
                // use the ShellHeader for compatibility reasons
                this.#oShellBar = Element.getElementById("shell-header");
            }
        }

        /**
         * Gets the notifications button by ID as it would be expected in the ShellHeader.
         * In case the ShellBar is used this method returns undefined as the button is not available.
         *
         * @returns {sap.ushell.ui.shell.ShellHeadItem|undefined} The notifications button or undefined if not available.
         * @since 1.142.0
         * @private
         */
        #getShellHeaderNotificationsButton () {
            if (this.#isShellBar()) {
                // only available in ShellBar
                return;
            }
            return Element.getElementById("NotificationsCountButton");
        }

        /**
         * Checks if the ShellBar instance is available. This is used as long as the ShellHeader may still be used.
         *
         * @returns {boolean} True if the ShellBar instance is available, false otherwise.
         * @since 1.142.0
         * @private
         */
        #isShellBar () {
            return this.#oShellBar?.isA("sap.f.gen.ui5.webcomponents_fiori.dist.ShellBar");
        }

        /**
         * Sets the notifications count.
         *
         * @param {int} iCount The notifications count to set.
         * @since 1.142.0
         * @private
         * @ui5-restricted ANS
         */
        setNotificationsCount (iCount) {
            if (this.#isShellBar()) {
                // need to map 0 to undefined as ShellBar would show "0" otherwise
                this.#oShellBar.setNotificationsCount(iCount || undefined);
            } else {
                this.#getShellHeaderNotificationsButton()?.setFloatingNumber(iCount);
            }
        }

        /**
         * Gets the notifications count.
         *
         * @returns {int} The current notifications count.
         * @since 1.142.0
         * @private
         * @ui5-restricted ANS
         */
        getNotificationsCount () {
            if (this.#isShellBar()) {
                return parseInt(this.#oShellBar.getNotificationsCount(), 10) || 0;
            }
            return this.#getShellHeaderNotificationsButton()?.getFloatingNumber();
        }

        /**
         * Binds the notifications count property to a model. The model value must be compatible with
         * the value of @see #setNotificationsCount.
         *
         * @param {string} sPath Absolute path to the property in the model.
         * @param {sap.ui.model.Model} oModel The model to bind to.
         * @since 1.142.0
         * @private
         * @ui5-restricted ANS
         */
        bindNotificationsCount (sPath, oModel) {
            this.bindModelProperty(sPath, oModel, "notificationsCount", this.setNotificationsCount.bind(this));
        }

        /**
         * Unbinds the notifications count property from a model.
         *
         * @since 1.142.0
         * @private
         * @ui5-restricted ANS
         */
        unbindNotificationsCount () {
            this.unbindModelProperty("notificationsCount");
        }

        /**
         * Sets whether notifications should be currently shown.
         * The actual value can differ from the set value due FLP state management.
         *
         * @param {boolean} bShow Whether to show notifications.
         * @since 1.142.0
         * @private
         * @ui5-restricted ANS
         */
        setShowNotifications (bShow) {
            StateManager.updateAllBaseStates("header.notifications.visible", Operation.Set, bShow);
        }

        /**
         * Returns whether notifications are currently shown.
         * The returned value can differ from last set value due FLP state management.
         *
         * @returns {boolean} Whether notifications are shown.
         * @since 1.142.0
         * @private
         * @ui5-restricted ANS
         */
        getShowNotifications () {
            if (this.#isShellBar()) {
                return this.#oShellBar.getShowNotifications();
            }
            return this.#getShellHeaderNotificationsButton()?.getVisible();
        }

        /**
         * Binds the the notifaction visibility to a model. The model value must be compatible with
         * the value of @see #setShowNotifications.
         *
         * @param {string} sPath Absolute path to the property in the model.
         * @param {sap.ui.model.Model} oModel The model to bind to.
         * @since 1.142.0
         * @private
         * @ui5-restricted ANS
         */
        bindShowNotifications (sPath, oModel) {
            this.bindModelProperty(sPath, oModel, "showNotifications", this.setShowNotifications.bind(this));
        }

        /**
         * Unbinds the notifaction visibility.
         *
         * @since 1.142.0
         * @private
         * @ui5-restricted ANS
         */
        unbindShowNotifications () {
            this.unbindModelProperty("showNotifications");
        }

        /**
         * Attaches a handler to the notifications press event.
         *
         * @param {object} [oData] An object that will be passed to the handler along with the event object when the event is fired
         * @param {function} fnFunction The handler function to call when the event occurs.
         * This function will be called in the context of the oListener instance (if present)
         * or on the event provider instance. The event object (@see: sap.ui.base.Event) is provided
         * as first argument of the handler. Handlers must not change the content of the event.
         * The second argument is the specified oData instance (if present).
         * @param {object} [oListener] The object that wants to be notified when the event occurs (this context within the handler function).
         *
         * @since 1.142.0
         * @private
         * @ui5-restricted ANS
         */
        attachNotificationsPress (...args) {
            if (this.#isShellBar()) {
                this.#oShellBar.attachNotificationsClick(...args);
            } else {
                this.#getShellHeaderNotificationsButton()?.attachPress(...args);
            }
        }

        /**
         * Detaches a handler from the notifications press event.
         *
         * @param {function} fnFunction The handler function to detach from the event.
         * @param {object} [oListener] The object that wanted to be notified when the event occurred.
         *
         * @since 1.142.0
         * @private
         * @ui5-restricted ANS
         */
        detachNotificationsPress (...args) {
            if (this.#isShellBar()) {
                this.#oShellBar.detachNotificationsClick(...args);
            } else {
                this.#getShellHeaderNotificationsButton()?.detachPress(...args);
            }
        }

        /**
         * Gets the DOM reference for the notifications area.
         *
         * @returns {Element} The DOM reference.
         * @since 1.142.0
         * @private
         * @ui5-restricted ANS
         */
        getNotificationsDomRef () {
            if (this.#isShellBar()) {
                return this.#oShellBar.getNotificationsDomRef();
            }
            return this.#getShellHeaderNotificationsButton()?.getDomRef();
        }
    }

    return NotificationsAPI;
});
