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

sap.ui.define([
    "sap/base/Log",
    "sap/base/util/deepClone",
    "sap/m/Bar",
    "sap/m/Button",
    "sap/m/library",
    "sap/m/MessageToast",
    "sap/m/ToolbarSpacer",
    "sap/ushell/components/pages/controller/PagesAndSpaceId",
    "sap/ushell/Container",
    "sap/ushell/EventHub",
    "sap/ushell/resources",
    "sap/ushell/utils/workpage/UserHomeService",
    "sap/ushell/utils/workpage/WorkPageService"
], (
    Log,
    deepClone,
    Bar,
    Button,
    mobileLibrary,
    MessageToast,
    ToolbarSpacer,
    PagesAndSpaceId,
    Container,
    EventHub,
    resources,
    UserHomeService,
    WorkPageService
) => {
    "use strict";

    /**
     * @alias sap.ushell.components.workpages.UserHomeUIUtils
     * @class
     * @classdesc Utility for managing User Home (My Space) UI components
     *
     * @since 1.148.0
     * @private
     */
    class UserHomeUIUtils {
        #oWorkPageRuntimeComponent;
        #oPage;
        #bIsEditMode;
        #oContainerRouter;
        #fnRouteHandler;
        #oOriginalPageData;
        #oWorkPageService;
        #oEnterEditModeButton;
        #oExitEditModeButton;
        #oFooter;

        /**
         * Creates a new UserHomeUIUtils instance
         * @param {sap.workzone.dws.workPageBuilder} oWorkPageRuntimeComponent The workpage runtime component, used to edit the page and save changes.
         * @param {sap.m.Page} oPage The UI5 page that contains the Work Page Runtime.
         *
         * @since 1.148
         * @private
         */
        constructor (oWorkPageRuntimeComponent, oPage) {
            this.#oWorkPageRuntimeComponent = oWorkPageRuntimeComponent;
            this.#oPage = oPage;
            this.#bIsEditMode = false;
            this.#oContainerRouter = null;
            this.#fnRouteHandler = this.#updateEditModeButtonVisibility.bind(this);
            this.#oOriginalPageData = null;
            this.#oWorkPageService = new WorkPageService();
            this.#oEnterEditModeButton = null;
            this.#oExitEditModeButton = null;
            this.#oFooter = null;
        }

        /**
         * Creates the Edit Mode buttons in the user actions menu and attaches
         * route-change listeners for visibility management.
         *
         * @returns {Promise} Resolves when the buttons are created
         * @since 1.148.0
         * @private
         */
        async createEditModeButton () {
            const oExtension = await Container.getServiceAsync("Extension");
            this.#oEnterEditModeButton = await oExtension.createUserAction({
                text: resources.i18n.getText("PageRuntime.EditMode.Activate"),
                icon: "sap-icon://edit",
                press: this.#toggleEditMode.bind(this)
            }, {
                helpId: "editModeBtn"
            });

            this.#oExitEditModeButton = await oExtension.createUserAction({
                text: resources.i18n.getText("PageRuntime.EditMode.Exit"),
                icon: "sap-icon://edit",
                press: this.#toggleEditMode.bind(this)
            }, {
                helpId: "editModeBtn"
            });

            this.#oContainerRouter = Container.getRendererInternal().getRouter();
            this.#oContainerRouter.getRoute("home").attachMatched(this.#fnRouteHandler);
            this.#oContainerRouter.getRoute("openFLPPage").attachMatched(this.#fnRouteHandler);

            await this.#updateEditModeButtonVisibility();
        }

        /**
         * Creates the footer for the workpage after enabling edit mode.
         * Footer contains Save and Cancel buttons.
         *
         * @since 1.148.0
         * @private
         */
        #createFooter () {
            if (this.#oFooter) {
                this.#oFooter.setVisible(this.#bIsEditMode);
                return;
            }

            this.#oFooter = new Bar("sapUshellMySpaceFooter", {
                visible: this.#bIsEditMode,
                contentRight: [
                    new ToolbarSpacer(),
                    new Button("sapUshellMySpaceFooterSaveBtn", {
                        type: mobileLibrary.ButtonType.Emphasized,
                        text: resources.i18n.getText("saveBtn"),
                        press: this.#pressSaveButton.bind(this)
                    }),
                    new Button("sapUshellMySpaceFooterCancelBtn", {
                        type: mobileLibrary.ButtonType.Default,
                        text: resources.i18n.getText("cancelBtn"),
                        press: this.#pressCancelButton.bind(this)
                    })
                ]
            });
            this.#oPage.setFooter(this.#oFooter);
        }

        /**
         * Toggles the workpagebuilder edit mode.
         *
         * @since 1.148.0
         * @private
         */
        async #toggleEditMode () {
            const bEntering = !this.#bIsEditMode;

            try {
                this.#oWorkPageRuntimeComponent.setMode(bEntering ? "edit" : "display");

                if (bEntering) {
                    await this.#storeOriginalPageData();
                }
            } catch (oError) {
                Log.error("Failed to toggle edit mode", oError, "sap.ushell.components.workpages.UserHomeUIUtils");
                return;
            }

            this.#bIsEditMode = bEntering;
            EventHub.emit("enableMenuBarNavigation", !bEntering);

            if (bEntering) {
                this.#oEnterEditModeButton.hideOnHome();
                this.#oExitEditModeButton.showOnHome();
            } else {
                this.#oEnterEditModeButton.showOnHome();
                this.#oExitEditModeButton.hideOnHome();
            }

            this.#createFooter();
        }

        /**
         * Stores a snapshot of the current page data so it can be restored on cancel.
         *
         * @returns {Promise} Resolves when the page data has been stored
         * @since 1.148.0
         * @private
         */
        async #storeOriginalPageData () {
            const oPageBuilder = this.#oWorkPageRuntimeComponent.getRootControl();
            const oInstance = await oPageBuilder._oInstance;
            this.#oOriginalPageData = deepClone(oInstance.getPageData(), 20);
        }

        /**
         * Destroys the edit mode button and cleans up edit mode state.
         *
         * @since 1.148.0
         */
        destroyEditModeButton () {
            if (this.#bIsEditMode) {
                EventHub.emit("enableMenuBarNavigation", true);
                this.#bIsEditMode = false;
            }

            this.#oContainerRouter.getRoute("home").detachMatched(this.#fnRouteHandler);
            this.#oContainerRouter.getRoute("openFLPPage").detachMatched(this.#fnRouteHandler);

            if (this.#oWorkPageRuntimeComponent && !this.#oWorkPageRuntimeComponent.bIsDestroyed) {
                this.#oWorkPageRuntimeComponent.setMode("display");
            }

            this.#oEnterEditModeButton?.destroy();
            this.#oExitEditModeButton?.destroy();
            this.#oFooter?.destroy();
        }

        /**
         * Handler for the Save button press.
         * Fetches the updated workpage content, reflects changes on the workpage builder and saves changes to the content api.
         *
         * @since 1.148.0
         * @private
         */
        async #pressSaveButton () {
            const oPageBuilder = this.#oWorkPageRuntimeComponent.getRootControl();

            try {
                const oInstance = await oPageBuilder._oInstance;
                const oPageData = oInstance.getPageData();

                await this.#oWorkPageService.updateWorkPage(oPageData);

                oPageBuilder.setPageData({
                    workPage: {
                        contents: oPageData,
                        usedVisualizations: { nodes: oPageBuilder.usedVisualizations || [] }
                    }
                });

                await this.#toggleEditMode();
                MessageToast.show(resources.i18n.getText("savedChanges"));
            } catch (oError) {
                Log.error("Failed to save My Space changes", oError, "sap.ushell.components.workpages.UserHomeUIUtils");
            }
        }

        /**
         * Handler for the Cancel button press. Exits edit mode without saving
         * and restores the original page data.
         *
         * @since 1.148.0
         * @private
         */
        async #pressCancelButton () {
            if (this.#oOriginalPageData) {
                const oPageBuilder = this.#oWorkPageRuntimeComponent.getRootControl();
                oPageBuilder.setPageData({
                    workPage: {
                        contents: this.#oOriginalPageData,
                        usedVisualizations: { nodes: oPageBuilder.usedVisualizations || [] }
                    }
                });
            }
            await this.#toggleEditMode();
        }

        /**
         * Updates the visibility of the Edit Mode button based on whether the user is on their My Space workpage.
         *
         * @since 1.148.0
         * @private
         */
        async #updateEditModeButtonVisibility () {
            if (this.#bIsEditMode) {
                // When navigating away while in edit mode (e.g. to an App) we should cancel the edits.
                await this.#pressCancelButton();
            }

            this.#oExitEditModeButton.hideOnHome();

            try {
                const oPageIds = await PagesAndSpaceId.getPageAndSpaceId();
                const sPageId = oPageIds?.pageId;

                if (!sPageId) {
                    this.#oEnterEditModeButton.hideOnHome();
                    return;
                }

                const oPersData = await UserHomeService.getPersData();
                const bIsEditable = oPersData.workpageId === sPageId;

                if (bIsEditable) {
                    this.#oEnterEditModeButton.showOnHome();
                } else {
                    this.#oEnterEditModeButton.hideOnHome();
                }
            } catch (oError) {
                Log.error("Failed to update edit mode button visibility", oError, "sap.ushell.components.workpages.UserHomeUIUtils");
                this.#oEnterEditModeButton.hideOnHome();
            }
        }
    }

    return UserHomeUIUtils;
});
