"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppProvider = void 0;
const ux_specification_types_1 = require("@sap/ux-specification-types");
const utils_1 = require("./utils");
/**
 * Retrieves the full name of a custom page based on its properties.
 * It attempts to use the `name` property of the `view` object,
 * falling back to the `template` property if `name` is undefined, or an empty string if both are absent.
 *
 * @param page The page object.
 * @returns The name of the page.
 */
function getCustomPageFullName(page) {
    let pageName = '';
    if ('view' in page) {
        pageName = page.view.name ?? '';
    }
    return pageName;
}
/**
 * Splits and returns the name of a custom page.
 *
 * @param {v4.Page|v2.Page} page - custom page
 * @returns {string} custom page name
 */
function getCustomPageName(page) {
    const viewName = getCustomPageFullName(page);
    const targetName = viewName.split('.');
    return targetName[targetName.length - 1];
}
/**
 * Returns the view type of a custom page.
 *
 * @param {v4.Page|v2.Page} page - custom page
 * @param {Application} app - application
 * @returns {string} view type
 */
function getViewType(page, app) {
    const viewType = page?.view?.viewType || app.settings?.viewType;
    return viewType || ux_specification_types_1.ViewTypes.XML;
}
/**
 * Returns file extension name for the page view type of a custom page.
 *
 * @param {v4.Page|v2.Page} page - custom page
 * @param {Application} app - application
 * @returns {string} File extension name of page view type
 */
function getViewTypeExtension(page, app) {
    return getViewType(page, app).toLowerCase();
}
/**
 * Returns the view path and file name of the custom page.
 *
 * @param page - custom page
 * @param app - application
 * @param viewPath - The initial view path segments for the custom page.
 * @returns view path
 */
function getViewPath(page, app, viewPath) {
    const splitViewPath = (splitPath) => {
        return splitPath.split(`${app.id}.`)[1]?.split('.');
    };
    const appSettings = app.settings;
    const appPath = page.view?.viewPath || appSettings?.viewPath;
    const pageName = getCustomPageFullName(page);
    if (pageName?.includes(app.id)) {
        viewPath = splitViewPath(pageName);
    }
    else if (appPath?.includes(app.id)) {
        viewPath = [...splitViewPath(appPath), ...pageName.split('.')];
    }
    const [pathParts, fileName] = [viewPath.slice(0, -1), ...viewPath.slice(-1)];
    return { viewPath: pathParts, fileName };
}
/**
 * Returns the page name and path of a custom page.
 *
 * @param page - custom page
 * @param app - The application object containing settings and metadata.
 * @returns page name
 */
function getCustomPagePath(page, app) {
    const viewName = page.entitySet || getCustomPageName(page);
    const { viewPath, fileName } = getViewPath(page, app, [viewName]);
    const viewType = getViewTypeExtension(page, app);
    // we always use '/' as separator so that snapshot tests generated from Windows do not fail on Jenkins
    return [...viewPath, `${fileName}.view.${viewType}`].join('/');
}
class AppProvider {
    /**
     * Creates an instance of AppProvider.
     *
     * @param importParameters - Parameters required for importing configurations, including manifest and schemas.
     * @param home - The home page ID of the application.
     * @param pages - The pages object containing all application pages.
     * @param settings - Optional application settings for V2 or V4.
     */
    constructor(importParameters, home, pages, settings) {
        // Store controller names which should be handled lately
        this.unhandledControllers = [];
        const schemaFile = (0, utils_1.getSchemaFilePath)(ux_specification_types_1.SchemaType.Application);
        this.app = {
            $schema: schemaFile.path,
            id: importParameters.manifest['sap.app'].id,
            pages,
            home,
            target: {},
            ...(settings && { settings })
        };
        if (importParameters.fioriElementsVersion) {
            this.app.target = {
                fioriElements: importParameters.fioriElementsVersion,
                odata: importParameters.oDataVersion
            };
        }
        else if (importParameters.oDataVersion) {
            this.app.target.odata = importParameters.oDataVersion;
        }
        this.schemas = importParameters.appSchemas;
        this.logger = importParameters.logger;
    }
    /**
     * Creates configuration files for the app (app.json) and pages (pages/{name}.json).
     * This is essentially a copy of createFiles optimized for use in FTFS:
     * It always uses POSIX path notation with forward slashes (/).
     *
     * @returns app and page files as separate objects
     */
    createConfigFiles() {
        const pageConfigs = {};
        const appConfig = {};
        let page;
        // add schema reference to all pages
        for (const pageId in this.app.pages) {
            page = this.app.pages[pageId];
            const schemaSuffix = this.app.target?.odata === ux_specification_types_1.OdataVersion.v4 ? pageId : page.entitySet;
            const config = this.getPageConfigFile(page, schemaSuffix);
            if (config) {
                pageConfigs[`${ux_specification_types_1.DirName.Pages}/${pageId}.json`] = config;
            }
        }
        // remove config before converting to JSON
        const app = JSON.parse(JSON.stringify(this.app));
        for (const pageId in app.pages) {
            delete app.pages[pageId].config;
        }
        appConfig[ux_specification_types_1.FileName.App] = app;
        return { appConfig, pageConfigs };
    }
    /**
     * Method returns page's config object to store in file for passed page.
     *
     * @param {v2.Page | v4.Page} page Page from 'app.json'.
     * @param {string} pageId - ID of the page or entity set in case of V2.
     * @returns {PageConfig | undefined} The page's config object to store in a file.
     */
    getPageConfigFile(page, pageId) {
        let config;
        const isEditableXML = getViewType(page, this.app) === ux_specification_types_1.ViewTypes.XML && !!page.config;
        if (page.pageType === ux_specification_types_1.PageTypeV4.CustomPage || (page.pageType === ux_specification_types_1.PageTypeV4.FPMCustomPage && !isEditableXML)) {
            const { path: $schema } = (0, utils_1.getSchemaFilePath)(page.pageType);
            config = { $schema };
        }
        else if (page.config) {
            config = page.config;
            const viewId = 'view' in page ? page.view?.id : undefined;
            const schemaFile = (0, utils_1.getSchemaFilePath)(page.pageType, pageId, viewId);
            if (this.schemas[schemaFile.filename]) {
                config.$schema = schemaFile.path;
            }
            else {
                const genericSchemaFile = (0, utils_1.getSchemaFilePath)(page.pageType);
                config.$schema = genericSchemaFile.path;
            }
        }
        if ((config && page.pageType === ux_specification_types_1.PageTypeV4.CustomPage) || page.pageType === ux_specification_types_1.PageTypeV4.FPMCustomPage) {
            this.applyCustomPageFilePath(page, config);
        }
        return config;
    }
    /**
     * Method updates "$filePath" property for custom page's config object.
     *
     * @param {v4.Page} page Custom page from 'app.json'.
     * @param {CustomPageConfig} config Custom page's config object.
     * @returns {void} This method does not return a value.
     */
    applyCustomPageFilePath(page, config) {
        const $filePath = getCustomPagePath(page, this.app);
        config.$filePath = $filePath;
    }
}
exports.AppProvider = AppProvider;
//# sourceMappingURL=appProvider.js.map