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

/**
 * @fileOverview The CurrentApplication module of the AppLifeCycle service
 *
 * @version 1.148.1
 */
sap.ui.define([
    "sap/ui/thirdparty/hasher",
    "sap/ui/thirdparty/URI",
    "sap/ushell/AppInfoParameters",
    "sap/ushell/Container",
    "sap/ushell/services/AppConfiguration",
    "sap/ushell/base/TechnicalParameters"
], (
    hasher,
    URI,
    AppInfoParameters,
    Container,
    AppConfiguration,
    TechnicalParameters
) => {
    "use strict";

    /**
     * @typedef {Object<string, any>} sap.ushell.services.AppLifeCycle.AppInfo
     * Defines the application info. Key-value pairs of application info parameters and their values.
     *
     * @since 1.120.0
     * @public
     */

    /**
     * @typedef {Object<string, sap.ushell.services.AppLifeCycle.AppInfoMetadataEntry>} sap.ushell.services.AppLifeCycle.AppInfoMetadata
     * Defines the application info. Key-value pairs of application info parameters and their values.
     *
     * @since 1.145.0
     * @private
     */

    /**
     * @typedef {object} sap.ushell.services.AppLifeCycle.AppInfoMetadataEntry
     * Defines the application info metadata.
     * @property {string} value The value of the parameter.
     * @property {boolean} [showInAbout] Whether the parameter should be shown in the about dialog.
     * @property {string} [label] The label of the parameter
     *
     * @since 1.131.0
     * @private
     */

    /**
     * @alias sap.ushell.services.AppLifeCycle.CurrentApplication
     * @class
     * @classdesc Defines the current application.
     * This object is only valid until the next application navigation.
     * Fetch it again from the AppLifeCycle service in the appLoaded event.
     *
     * @hideconstructor
     * @see sap.ushell.services.AppLifeCycle#getCurrentApplication
     * @see sap.ushell.services.AppLifeCycle#attachAppLoaded
     *
     * @since 1.120.0
     * @public
    */
    class CurrentApplication {
        #oApplicationContainer;
        #sApplicationType;
        #oComponentInstance;
        #bHomePage;
        #fnUseLegacyRestoreFlowForCurrentApplication;
        #bDestroyed = false;

        constructor (sApplicationType, oComponentInstance, bHomePage, oApplicationContainer, fnUseLegacyRestoreFlowForCurrentApplication) {
            this.#oApplicationContainer = oApplicationContainer;
            this.#sApplicationType = sApplicationType;
            this.#oComponentInstance = oComponentInstance;
            this.#bHomePage = bHomePage;
            this.#fnUseLegacyRestoreFlowForCurrentApplication = fnUseLegacyRestoreFlowForCurrentApplication;
        }

        #checkDestroyed () {
            if (this.#bDestroyed) {
                throw new Error("CurrentApplication instance is destroyed. Fetch a new instance from the AppLifeCycle service.");
            }
        }

        /**
         * @type {sap.ushell.services.AppLifeCycle.ApplicationType}
         * The type of the current application.
         *
         * @readonly
         *
         * @since 1.120.0
         * @public
         */
        get applicationType () {
            this.#checkDestroyed();
            return this.#sApplicationType;
        }

        set applicationType (sApplicationType) {
            this.#checkDestroyed();
            throw new Error("Property 'applicationType' is read-only.");
        }

        /**
         * @type {sap.ui.core.Component|null}
         * Reference to component. Only available for applicationType "UI5"
         *
         * @readonly
         *
         * @since 1.120.0
         * @public
         */
        get componentInstance () {
            this.#checkDestroyed();
            return this.#oComponentInstance;
        }

        set componentInstance (oComponentInstance) {
            this.#checkDestroyed();
            throw new Error("Property 'componentInstance' is read-only.");
        }

        /**
         * @type {boolean}
         * <code>true</code> when root intent (normally #Shell-home) or Appfinder (#Shell-appfinder) is currently displayed.
         *
         * @readonly
         *
         * @since 1.120.0
         * @public
         */
        get homePage () {
            this.#checkDestroyed();
            return this.#bHomePage;
        }

        set homePage (bHomePage) {
            this.#checkDestroyed();
            throw new Error("Property 'homePage' is read-only.");
        }

        /**
         * function that returns the value of a technical parameter for the given application.
         * This method is for SAP internal usage only.
         * @param {string} sParameterName The name of the technical parameter
         * @returns {Promise<string>} A promise that resolves with the value of the technical parameter
         *
         * @since 1.120.0
         * @public
         */
        async getTechnicalParameter (sParameterName) {
            this.#checkDestroyed();

            return TechnicalParameters.getParameterValue(
                sParameterName,
                this.#oComponentInstance,
                this.#oApplicationContainer,
                this.#sApplicationType
            );
        }

        /**
         * See {@link sap.ushell.services.URLParsing#parseShellHash} for details.
         * <i>This method is for SAP-internal use only!</i>
         * @param {boolean} bRealAppIntent If set to true, the intent is extracted from the real application URL in case of a remote app
         * @returns {Promise<sap.ushell.services.URLParsing.DecomposedHash>} A promise that resolves with the intent of the current application
         *
         * @since 1.120.0
         * @public
         */
        async getIntent (bRealAppIntent) {
            this.#checkDestroyed();

            const sHash = hasher.getHash();
            if (!sHash) {
                throw new Error("Could not identify current application hash");
            }

            const URLParsing = await Container.getServiceAsync("URLParsing");

            const oParsedHash = URLParsing.parseShellHash(sHash);
            if (bRealAppIntent && this.#oApplicationContainer) {
                const sAppUrl = this.#oApplicationContainer.getCurrentAppUrl();
                if (sAppUrl) {
                    const oUriParams = new URI(sAppUrl).search(true);
                    if (oUriParams.hasOwnProperty("sap-remote-intent")) {
                        oParsedHash.semanticObject = oUriParams["sap-remote-intent"].split("-")[0];
                        oParsedHash.action = oUriParams["sap-remote-intent"].split("-")[1];
                        delete oParsedHash.params["sap-shell-so"];
                        delete oParsedHash.params["sap-shell-action"];
                    }
                }
            }
            return oParsedHash;
        }

        /**
         * A function to collect the values of the given parameters
         * @param {Array<sap.ushell.services.AppLifeCycle.AppInfoParameterName>} aParameterNames Array of requested parameters
         * @returns {Promise<sap.ushell.services.AppLifeCycle.AppInfo>} Resolves to an object
         *    keeping the application info parameters with values
         *
         * @since 1.120.0
         * @public
         */
        async getInfo (aParameterNames) {
            this.#checkDestroyed();

            return AppInfoParameters.getInfo(
                aParameterNames,
                this,
                this.#oApplicationContainer
            );
        }

        /**
         * Returns all application info parameters with values related to this application.
         *
         * @example
         *   const oResultWithValuesOnly = {
         *       appFrameworkId: "UI5",
         *       appId: "F1234",
         *       productName: "SAP Fiori launchpad",
         *       "custom.property": "customValue"
         *   };
         *   const oResultWithMetadata = {
         *       appFrameworkId: { value: "UI5" },
         *       appId: { value: "F1234" },
         *       productName: { value: "SAP Fiori launchpad" },
         *       "custom.property": { value: "customValue", showInABout: true, label: "Custom Property" }
         *   };
         * @param {boolean} bValues Whether to return the metadata or just the values.
         * @returns {Promise<sap.ushell.services.AppLifeCycle.AppInfo>|Promise<sap.ushell.services.AppLifeCycle.AppInfoMetadata>} Object containing the application info parameters with values.
         *
         * @private
         */
        async getAllAppInfo (bValues) {
            this.#checkDestroyed();

            const oData = await AppInfoParameters.getAllAppInfo(bValues, this, this.#oComponentInstance, this.#oApplicationContainer);

            if (bValues) {
                oData.applicationType = this.#sApplicationType;
                oData.homePage = this.#bHomePage;
            } else {
                oData.applicationType = { value: this.#sApplicationType };
                oData.homePage = { value: this.#bHomePage };
            }

            return oData;
        }

        /**
         * Returns the system context of the current application.
         * @returns {Promise<sap.ushell.services.ClientSideTargetResolution.SystemContext>} The system context of the current application.
         *
         * @private
         */
        async getSystemContext () {
            this.#checkDestroyed();

            const oCurrentApp = AppConfiguration.getCurrentApplication() || {};
            const sContentProviderId = oCurrentApp.contentProviderId /* a content provider id */ || ""/* i.e., the local system */;

            const ClientSideTargetResolution = await Container.getServiceAsync("ClientSideTargetResolution");
            return ClientSideTargetResolution.getSystemContext(sContentProviderId);
        }

        /**
         * Emits an event when disableKeepAliveAppRouterRetrigger API is called
         * This API should be used only by Fiori Elements team
         *
         * @param {boolean} bDisableRouterRetrigger
         *     A flag to disable or enable the router's re-trigger
         *     when a keep-alive application is restored
         *
         * @since 1.98
         * @private
         * @ui5-restricted sap.fe
         */
        disableKeepAliveAppRouterRetrigger (bDisableRouterRetrigger) {
            this.#checkDestroyed();

            this.#fnUseLegacyRestoreFlowForCurrentApplication(
                this.#oComponentInstance?.oContainer?.sId,
                bDisableRouterRetrigger
            );
        }

        /**
         * Destroys this CurrentApplication instance.
         *
         * @since 1.145.0
         * @private
         */
        destroy () {
            this.#bDestroyed = true;
        }
    }

    return CurrentApplication;
});
