// Copyright (c) 2009-2026 SAP SE, All Rights Reserved
/**
 * @fileOverview handle all the resources for the different applications.
 * @version 1.145.3
 */
sap.ui.define([
    "sap/ui/core/EventBus",
    "sap/ushell/appIntegration/ApplicationContainerCache",
    "sap/ushell/Container",
    "sap/ushell/resources",
    "sap/ushell/UI5ComponentType",
    "sap/ushell/utils",
    "sap/ushell/utils/LaunchpadError",
    "sap/ushell/utils/UrlParsing"
], (
    EventBus,
    ApplicationContainerCache,
    Container,
    ushellResources,
    UI5ComponentType,
    ushellUtils,
    LaunchpadError,
    UrlParsing
) => {
    "use strict";

    class EmbeddedUI5Handler {
        async createApp (oApplicationContainer, oResolvedHashFragment, oParsedHash) {
            // We need to stop every application router to avoid inner-app hash change clashes
            // before creating a new component.
            ApplicationContainerCache.forEach((oCachedApplicationContainer) => {
                if (oCachedApplicationContainer === oApplicationContainer) {
                    return;
                }

                if (oCachedApplicationContainer.isA("sap.ushell.appIntegration.UI5ApplicationContainer")) {
                    oCachedApplicationContainer.stopRouter();
                }
            });

            // load ui5 component via service; core-ext-light will be loaded as part of the asyncHints
            const Ui5ComponentLoader = await Container.getServiceAsync("Ui5ComponentLoader");

            const sBasicHash = UrlParsing.constructBasicHash(oParsedHash);
            oResolvedHashFragment.ui5ComponentId = `application-${sBasicHash}-component`;
            oApplicationContainer.setUi5ComponentId(oResolvedHashFragment.ui5ComponentId);

            try {
                await Ui5ComponentLoader.createComponent(
                    oResolvedHashFragment,
                    [],
                    UI5ComponentType.Application
                );
            } catch (oError) {
                const sShellHash = UrlParsing.constructShellHash(oParsedHash, true);

                const oUpdatedError = new LaunchpadError(
                    oError.message,
                    {
                        translatedMessage: ushellResources.i18n.getText("failed_to_open_ui5_component"),
                        messageDetails: ushellResources.i18n.getText("cannot_load_ui5_component_details", [sShellHash])
                    },
                    oError
                );

                throw oUpdatedError;
            }
        }

        async getNavigationRedirectHash (oApplicationContainer) {
            const oComponentHandle = oApplicationContainer.getComponentHandle();
            if (!oComponentHandle) {
                return;
            }

            const oComponent = oComponentHandle.getInstance({});
            if (!oComponent) {
                return;
            }

            if (typeof oComponent.navigationRedirect !== "function") {
                return;
            }

            // oComponent refers to a trampoline application
            const oNavRedirectThenable = oComponent.navigationRedirect();
            if (!oNavRedirectThenable || typeof oNavRedirectThenable.then !== "function") {
                return;
            }

            try {
                const sHash = await ushellUtils.promisify(oNavRedirectThenable);
                return sHash;
            } catch {
                // fail silently
            }
        }

        async storeApp (oApplicationContainer) {
            const oResolvedHashFragment = oApplicationContainer.getCurrentAppTargetResolution();
            EventBus.getInstance().publish("sap.ushell", "appKeepAliveDeactivate", oResolvedHashFragment);

            const oComponentHandle = oApplicationContainer.getComponentHandle();
            const oComponent = oComponentHandle.getInstance();

            // check first whether this app requires activate/deactivate
            if (oComponent.isKeepAliveSupported?.()) {
                oComponent.deactivate();
                return;
            }

            // fallback to suspend/restore
            if (typeof oComponent.suspend === "function") {
                oComponent.suspend();
            }

            const oRouter = oComponent.getRouter?.();
            if (oRouter && typeof oRouter.stop === "function") {
                oRouter.stop();
            }
        }

        async restoreAppAfterNavigate (oApplicationContainer, oStorageEntry) {
            const oResolvedHashFragment = oApplicationContainer.getCurrentAppTargetResolution();
            EventBus.getInstance().publish("sap.ushell", "appKeepAliveActivate", oResolvedHashFragment);

            const oComponentHandle = oApplicationContainer.getComponentHandle();
            const oComponent = oComponentHandle.getInstance();

            // check first whether this app requires activate/deactivate (more modern way)
            if (oComponent.isKeepAliveSupported?.()) {
                oComponent.activate();
                return;
            }

            // fallback to suspend/restore (old way)
            if (typeof oComponent.restore === "function") {
                oComponent.restore();
            }

            const oRouter = oComponent.getRouter?.();
            if (oRouter && typeof oRouter.initialize === "function") {
                // default is false, which just continues the router assuming the current hash did not change
                // can be overridden by FEv2 see AppLifeCycle.getCurrentApplication().disableKeepAliveAppRouterRetrigger()
                // this fully restarts the router and re-triggers the matching for the current hash
                const bIgnoreInitialHash = !oStorageEntry.useLegacyRestoreFlow;
                oRouter.initialize(bIgnoreInitialHash);
            }
        }
    }

    return new EmbeddedUI5Handler();
});
