"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCustomColumnPath = exports.SAP_UI_TABLE = exports.FRAGMENT_DEFINITION = void 0;
exports.getRootCustomColumnFromFragmentJSON = getRootCustomColumnFromFragmentJSON;
exports.deleteColumnFromFragment = deleteColumnFromFragment;
exports.exportCustomColumnsToFragment = exportCustomColumnsToFragment;
const ux_specification_types_1 = require("@sap/ux-specification-types");
const xml_js_1 = require("xml-js");
const view_controller_generator_1 = require("../view-controller-generator");
const i18next_1 = __importDefault(require("i18next"));
const extensionLogger_1 = require("../../../../extensionLogger");
const manifest_1 = require("../manifest");
const path_1 = require("path");
exports.FRAGMENT_DEFINITION = 'core:FragmentDefinition';
exports.SAP_UI_TABLE = 'sap.ui.table';
const VIEW_TEMPLATE_TAGTYPE_MAP = new Map([
    [ux_specification_types_1.ViewTemplateType.ResponsiveTableColumnsExtension, { namespace: 'sap.m', name: 'Column' }],
    [ux_specification_types_1.ViewTemplateType.TreeTableColumnsExtension, { namespace: exports.SAP_UI_TABLE, name: 'Column' }],
    [ux_specification_types_1.ViewTemplateType.GridTableColumnsExtension, { namespace: exports.SAP_UI_TABLE, name: 'Column' }],
    [ux_specification_types_1.ViewTemplateType.AnalyticalTableColumnsExtension, { namespace: exports.SAP_UI_TABLE, name: 'AnalyticalColumn' }]
]);
const FE_TEMPLATE_VIEW_EXTENSION_MAP = new Map([
    [ux_specification_types_1.v2.FE_TEMPLATE_V2_LIST_REPORT, ux_specification_types_1.v2.SAPUI5_VIEW_EXTENSION_LIST_REPORT],
    [ux_specification_types_1.v2.FE_TEMPLATE_V2_ALP, ux_specification_types_1.v2.SAPUI5_VIEW_EXTENSION_ANALYTICAL_LIST_PAGE],
    [ux_specification_types_1.v2.FE_TEMPLATE_V2_OBJECT_PAGE, ux_specification_types_1.v2.SAPUI5_VIEW_EXTENSION_OBJECT_PAGE]
]);
const dummyEntry = {
    type: 'element',
    name: 'Text',
    attributes: { text: 'Placeholder' }
};
const dummyEntryAsString = JSON.stringify(dummyEntry);
/**
 * Lists namespaces available in fragment to consider.
 *
 * @param fragment - fragment content
 * @param isCoreFragmentDefinition - If set to true, only the namespaces in core definition will be considered
 * @returns {Map<string, string[]> | undefined} - If available, namespaces will be returned as Map (key: alias, values: name[])
 */
function getFragmentNamespaces(fragment, isCoreFragmentDefinition) {
    const fragmentAttributes = isCoreFragmentDefinition
        ? fragment?.[exports.FRAGMENT_DEFINITION]?.['_attributes']
        : fragment?.['_attributes'];
    if (fragmentAttributes) {
        const allFragmentNamespaces = new Map();
        Object.keys(fragmentAttributes)
            .filter((attribute) => attribute.startsWith('xmlns'))
            .forEach((xmlns) => {
            const existingNamespaces = allFragmentNamespaces.get(fragmentAttributes[xmlns]);
            allFragmentNamespaces.set(fragmentAttributes[xmlns], existingNamespaces
                ? [...existingNamespaces, xmlns.split(':')[1] || xmlns]
                : [xmlns.split(':')[1] || xmlns]);
        });
        return allFragmentNamespaces;
    }
    else {
        throw new Error('Invalid fragment, please check content');
    }
}
/**
 * Considers namespace of fragment and returns combined tag name.
 *
 * @param tag - tag name and namespace
 * @param tag.namespace - The namespace of the tag
 * @param tag.name - The name of the tag
 * @param fragmentNamespaces namespaces of fragment
 * @returns {string} tag name consisting of namespace and name
 */
function getTagName(tag, fragmentNamespaces) {
    if (!fragmentNamespaces) {
        return `${tag.namespace}:${tag.name}`;
    }
    else if (fragmentNamespaces.includes('xmlns')) {
        return tag.name;
    }
    else {
        return `${fragmentNamespaces}:${tag.name}`;
    }
}
/**
 * Maps the column template type to the fragment namespace and returns the tag name with namespace of root column definition.
 *
 * @param definition - fragment or content definition
 * @param viewTemplateType - name of the view template that shall be applied
 * @param fragment - fragment definition
 * @returns {unknown | undefined} Root column tag name.
 */
function getTagNameFromFragmentJSON(definition, viewTemplateType, fragment = definition) {
    const namespaces = getFragmentNamespaces(fragment, viewTemplateType || fragment !== definition ? true : false);
    if (viewTemplateType) {
        const tag = VIEW_TEMPLATE_TAGTYPE_MAP.get(viewTemplateType);
        return getTagName(tag, namespaces.get(tag.namespace));
    }
    else {
        const keys = VIEW_TEMPLATE_TAGTYPE_MAP.keys();
        for (const key of keys) {
            const tag = VIEW_TEMPLATE_TAGTYPE_MAP.get(key);
            const tagName = namespaces ? getTagName(tag, namespaces.get(tag.namespace)) : tag.name;
            if (definition[tagName]) {
                return tagName;
            }
        }
    }
    return undefined;
}
/**
 * Method which receives fragment definition node and reads root column definition.
 *
 * @param {unknown} definition - Application or Page Config object.
 * @param {unknown} fragment - fragment definition
 * @returns {unknown | undefined} Root column read from definition.
 */
function getRootCustomColumnFromFragmentJSON(definition, fragment = definition) {
    const name = getTagNameFromFragmentJSON(definition, undefined, fragment);
    return definition[name];
}
/**
 * Internal function adding content to config column.
 *
 * @param configColumns - list of all columns in the config
 * @param columnIndex - index of column
 * @returns - filled personalization data
 */
function addP13nData(configColumns, columnIndex) {
    const columnProperties = [
        'id',
        'text',
        'className',
        'fragmentName',
        'tabKey',
        'extensionType',
        'cellsFragmentName'
    ];
    let p13nData = `\\{`;
    for (const key in configColumns[columnIndex]) {
        const value = configColumns[columnIndex][key];
        if (!columnProperties.includes(key) && value !== undefined && value.length !== 0) {
            if (p13nData !== '\\{') {
                p13nData += `, `;
            }
            p13nData += `"${key}": "${value.toString()}"`;
        }
    }
    p13nData += '}';
    return p13nData;
}
/**
 * Internal function handling a single fragment column if detected in the fragment.
 *
 * @param columnsInFragment - list of all columns in fragment
 * @param configColumns - list of all columns in the config
 * @returns - boolean value indicating if the column was found in the config
 */
function handleFragmentColumn(columnsInFragment, configColumns) {
    let foundInConfig = false;
    const customData = columnsInFragment['customData'] || columnsInFragment['table:customData'];
    if (!customData) {
        return false;
    }
    let p13nData = customData['core:CustomData']._attributes.value;
    const columnParts = JSON.parse(p13nData.substr(1, p13nData.length));
    const columnIndex = configColumns.findIndex((column) => {
        return column.columnKey === columnParts.columnKey;
    });
    if (columnIndex < 0) {
        return false;
    }
    //Found ==> update scenario
    foundInConfig = true;
    p13nData = addP13nData(configColumns, columnIndex);
    customData['core:CustomData']._attributes.value = p13nData;
    if (!columnsInFragment['Text'] && !columnsInFragment['Label'] && configColumns[columnIndex]?.text) {
        columnsInFragment['Text'] = {
            _attributes: {}
        };
    }
    if (columnsInFragment['Text'] && columnsInFragment['Text']['_attributes']) {
        columnsInFragment['Text']._attributes['text'] = configColumns[columnIndex]?.text;
    }
    else if (columnsInFragment['Label'] && columnsInFragment['Label']['_attributes']) {
        columnsInFragment['Label']._attributes['text'] = configColumns[columnIndex]?.text;
    }
    if (!columnsInFragment['_attributes']) {
        columnsInFragment['_attributes'] = {};
    }
    columnsInFragment['_attributes']['id'] = configColumns[columnIndex].id;
    configColumns.splice(columnIndex, 1);
    return foundInConfig;
}
/**
 * Deletes obsolete custom columns from the relevant fragment(s).
 *
 * @param manifestSection - Section in manifest.json comprising the extensions
 * @param fragments - list of all fragments
 * @param pattern - Search string to identify the extension in manifest
 * @param appId - application ID
 */
function deleteColumnsFromFragment(manifestSection, fragments, pattern, appId) {
    const fragmentId = manifestSection[pattern].fragmentName.substr(appId.length + 1);
    const fragmentType = manifestSection['type'] ? manifestSection['type'].toLowerCase() : 'xml';
    const fragmentParts = fragmentId.split('.');
    const fragmentName = fragmentParts[fragmentParts.length - 1] + ux_specification_types_1.FRAGMENTNAMEPART + fragmentType;
    for (const fragment of fragments) {
        const fragmentPathArray = fragment['dataSourceUri'].split(path_1.sep);
        if (fragmentPathArray[fragmentPathArray.length - 1] === fragmentName) {
            const fragmentJson = JSON.parse((0, xml_js_1.xml2json)(fragment.fileContent, { compact: true }));
            try {
                const tagName = getTagNameFromFragmentJSON(fragmentJson[exports.FRAGMENT_DEFINITION]);
                if (tagName) {
                    delete fragmentJson[exports.FRAGMENT_DEFINITION][tagName];
                    fragment.fileContent = (0, xml_js_1.json2xml)(JSON.stringify(fragmentJson), { compact: true, spaces: 4 });
                }
            }
            catch {
                throw new Error(`Invalid fragment ${fragment['dataSourceUri']}, please check content`);
            }
            break;
        }
    }
}
/**
 * Deletes a given number of (dummy) cells from a fragment.
 *
 * @param fragmentCells - list of all cells in the parsed fragment
 * @param noOfEntriesToBeDeleted - number of entries to be deleted
 */
function deleteNumberOfCells(fragmentCells, noOfEntriesToBeDeleted) {
    //only dummy entry will be deleted automatically!
    for (let index = 0; index < Object.keys(fragmentCells).length; index++) {
        if (JSON.stringify(fragmentCells[index]) === dummyEntryAsString) {
            fragmentCells.splice(index, 1);
            noOfEntriesToBeDeleted -= 1;
            if (noOfEntriesToBeDeleted === 0) {
                break;
            }
        }
    }
}
/**
 * Deletes cells from the relevant fragment.
 *
 * @param cellManifestSection - section in mnifest referring the cells'fragment
 * @param fragments - list of all fragments
 * @param appId - application ID
 */
function deleteCellsFromFragment(cellManifestSection, fragments, appId) {
    const fragmentType = cellManifestSection['type'] ? cellManifestSection['type'].toLowerCase() : 'xml';
    const fragmentParts = cellManifestSection['fragmentName'].substr(appId.length + 1).split('.');
    const fragmentName = fragmentParts[fragmentParts.length - 1] + ux_specification_types_1.FRAGMENTNAMEPART + fragmentType;
    for (const fragment of fragments) {
        if (fragment['dataSourceUri'].endsWith(fragmentName)) {
            const fragmentJson = JSON.parse((0, xml_js_1.xml2json)(fragment.fileContent));
            const fragmentCells = fragmentJson.elements[0].elements &&
                fragmentJson.elements[0].elements.filter((element) => {
                    return element.type === 'element';
                });
            if (fragmentCells) {
                deleteNumberOfCells(fragmentJson.elements[0].elements, fragmentCells.length);
            }
            fragment.fileContent = (0, xml_js_1.json2xml)(JSON.stringify(fragmentJson), { spaces: 4 });
            break;
        }
    }
}
/**
 * Identifies the right extensions based on a pattern, then deletes all corresponding columns and cells.
 *
 * @param manifestSection - Section in manifest.json comprising the extensions
 * @param pattern - Search string to identify the extension in manifest
 * @param appId - application ID
 * @param fragments - list of all fragments
 */
function deleteColumnFromFragment(manifestSection, pattern, appId, fragments) {
    if (fragments) {
        //delete columns
        deleteColumnsFromFragment(manifestSection, fragments, pattern, appId);
        //delete cells
        const cellsPath = pattern.replace(ux_specification_types_1.ViewTemplateType.ResponsiveTableColumnsExtension, ux_specification_types_1.ViewTemplateType.ResponsiveTableCellsExtension);
        const cellManifestSection = manifestSection[cellsPath];
        if (cellManifestSection) {
            deleteCellsFromFragment(cellManifestSection, fragments, appId);
        }
    }
}
/**
 * Adds new (dummy) columns to a given fragment, as many as we have entries in the config.
 *
 * @param fragmentCells - list of all cells in fragment
 * @param fragmentJson - complete fragment, parsed as JSON
 * @param config - actual config.json
 */
function addNewColumnsInFragment(fragmentCells, fragmentJson, config) {
    const startIndex = fragmentCells ? Object.keys(fragmentCells).length : 0;
    if (!fragmentJson.elements[0].elements) {
        fragmentJson.elements[0].elements = [];
    }
    for (let index = startIndex; index < Object.keys(config).length; index++) {
        fragmentJson.elements[0].elements.push(dummyEntry);
    }
}
/**
 * Updates non-empty cells in a given fragment, from the config information.
 *
 * @param fragment - identified cells' fragment
 * @param config - config.json that lists the new cells' information
 */
function updateNonEmptyCellsFragment(fragment, config) {
    const fragmentJson = JSON.parse((0, xml_js_1.xml2json)(fragment.fileContent));
    const fragmentCells = fragmentJson.elements[0].elements &&
        fragmentJson.elements[0].elements.filter((element) => {
            return element.type === 'element';
        });
    if (!fragmentCells || Object.keys(fragmentCells).length !== Object.keys(config).length) {
        if (!fragmentCells || Object.keys(fragmentCells).length < Object.keys(config).length) {
            addNewColumnsInFragment(fragmentCells, fragmentJson, config);
        }
        else if (Object.keys(fragmentCells).length > Object.keys(config).length) {
            const noOfEntriesToBeDeleted = Object.keys(fragmentCells).length - Object.keys(config).length;
            const fragmentElements = fragmentJson.elements[0].elements;
            deleteNumberOfCells(fragmentElements, noOfEntriesToBeDeleted);
        }
        fragment.fileContent = (0, xml_js_1.json2xml)(JSON.stringify(fragmentJson), { spaces: 4 });
    }
}
/**
 * Updates the content of a cell fragment file.
 *
 * @param fragments - list of existing fragments, to be enhanced
 * @param cellFragmentFileName - file name of the given cell fragment, as calculated from the config entry
 * @param config - current config JSON
 * @param generateId - function to generate ids for new entries in the fragment
 * @returns a boolean value to indicate if the cell fragment could be found n the given list of fragments
 */
function updateCellsFragment(fragments, cellFragmentFileName, config, generateId) {
    let cellsFragmentFound = false;
    for (const fragment of fragments) {
        const fragmentPathArray = fragment['dataSourceUri'].split(path_1.sep);
        if (fragmentPathArray[fragmentPathArray.length - 1] === cellFragmentFileName) {
            cellsFragmentFound = true;
            fragment.changeIndicator = ux_specification_types_1.ChangeIndicator.Updated;
            if (!fragment.fileContent || Object.keys(fragment.fileContent).length === 0) {
                // Empty fragment - use template
                fragment.fileContent = (0, view_controller_generator_1.getResponsiveTableCellsFragment)(config, generateId);
            }
            else {
                updateNonEmptyCellsFragment(fragment, config);
            }
            break;
        }
    }
    return cellsFragmentFound;
}
/**
 * Adapt manifest from the given custom columns' definition in manifest.
 *
 * @param manifestPath - path to the current section of the manifest that describes the extension
 * @param {ExportResults} exportResults - export result comprising fragments and manifest
 * @param config - current config part, describing the new image of the extension
 * @param appId - application ID
 * @param {ExtensionLogger} logger - logger instance for exceptions
 * @returns everything that is needed for further processing the fragment
 */
function exportCustomColumnsToManifest(manifestPath, exportResults, config, appId, logger) {
    let lsFilePath;
    let cellsFragmentName;
    const manifest = exportResults.manifest;
    const manifestSection = (0, manifest_1.ensureManifestSectionByPathV2)(manifest, manifestPath);
    const fragmentType = manifestSection['type'] ? manifestSection['type'].toLowerCase() : 'xml';
    manifestSection['type'] = fragmentType.toUpperCase();
    for (const configElement of config) {
        //last one wins -as there can only be one reference in the manifest
        if (!configElement.fragmentName) {
            (0, extensionLogger_1.log)(logger, {
                severity: "error" /* LogSeverity.Error */,
                message: i18next_1.default.t('NOFRAGMENT', { columnKey: configElement.columnKey })
            });
            continue;
        }
        exportResults.manifestChangeIndicator = ux_specification_types_1.ChangeIndicator.Updated;
        manifestSection['fragmentName'] = configElement.fragmentName;
        manifestSection['className'] = configElement.className;
        lsFilePath =
            configElement.fragmentName?.replace(appId, '<root>/webapp').replace(/[.]/g, path_1.sep) +
                ux_specification_types_1.FRAGMENTNAMEPART +
                fragmentType;
    }
    if (manifestPath.indexOf(ux_specification_types_1.ViewTemplateType.ResponsiveTableColumnsExtension) > -1) {
        exportResults.manifestChangeIndicator = ux_specification_types_1.ChangeIndicator.Updated;
        const cellsPath = manifestPath.replace(ux_specification_types_1.ViewTemplateType.ResponsiveTableColumnsExtension, ux_specification_types_1.ViewTemplateType.ResponsiveTableCellsExtension);
        const cellManifestSection = (0, manifest_1.ensureManifestSectionByPathV2)(manifest, cellsPath);
        const cellsFragmentColumn = config.reduce((previousColumn, column) => {
            return column.cellsFragmentName ? column : previousColumn;
        });
        if (cellsFragmentColumn && cellsFragmentColumn.cellsFragmentName) {
            cellManifestSection['fragmentName'] = cellsFragmentName = cellsFragmentColumn.cellsFragmentName;
            cellManifestSection['className'] = config[0].className;
            cellManifestSection['type'] = fragmentType.toUpperCase();
        }
        else {
            (0, manifest_1.deleteManifestSectionByPathV2)(manifest, cellsPath);
        }
    }
    return { manifestSection, lsFilePath, cellsFragmentName, fragmentType };
}
/**
 * Method inserts new custom column into array of existing columns in same place as it appears in column configs.
 *
 * @param column - Custom column config object.
 * @param viewTemplateType - template type
 * @param columnsInFragmentDefinition - Existing columns definition
 * @param fragment - fragment definition
 * @param colPos - column position from config
 * @param generateId - function to generate ids for new entries in the fragment
 * @returns - Columns object.
 */
function insertNewColumnInFragment(column, viewTemplateType, columnsInFragmentDefinition, fragment, colPos, generateId) {
    const newColumnFragment = (0, view_controller_generator_1.getSingleColumnContent)(column, viewTemplateType, generateId);
    if (newColumnFragment) {
        const newColumnDefinition = JSON.parse((0, xml_js_1.xml2json)(newColumnFragment, { compact: true }));
        const newColumn = getRootCustomColumnFromFragmentJSON(newColumnDefinition, fragment);
        if (Array.isArray(columnsInFragmentDefinition)) {
            // avoid having same columns
            const columnExists = columnsInFragmentDefinition.some((col) => JSON.stringify(col) === JSON.stringify(newColumn));
            if (!columnExists) {
                columnsInFragmentDefinition.push(newColumn);
            }
        }
        else {
            if (columnsInFragmentDefinition) {
                // insert new column in array at specific position
                const newColumnsInFragmentDefinition = [columnsInFragmentDefinition];
                newColumnsInFragmentDefinition.splice(colPos, 0, newColumn);
                columnsInFragmentDefinition = newColumnsInFragmentDefinition;
            }
            else {
                columnsInFragmentDefinition = [newColumn];
            }
        }
    }
    return columnsInFragmentDefinition;
}
/**
 * Processes custom columns in an array.
 *
 * @param columnsInFragmentDefinition - Existing columns definition in the fragment.
 * @param configColumns - Custom columns configuration object.
 */
function processCustomColumnInArray(columnsInFragmentDefinition, configColumns) {
    // store indexes of columns not appearing in config for later deletion
    const unexistingColumnIndicesInConfig = [];
    for (let j = 0; j < columnsInFragmentDefinition.length; j++) {
        const columnFoundInConfig = handleFragmentColumn(columnsInFragmentDefinition[j], configColumns);
        if (!columnFoundInConfig) {
            unexistingColumnIndicesInConfig.push(j);
        }
    }
    for (let i = unexistingColumnIndicesInConfig.length - 1; i >= 0; i--) {
        columnsInFragmentDefinition.splice(unexistingColumnIndicesInConfig[i], 1);
    }
}
/**
 * Maintains existing columns in a fragment by updating or removing them based on the provided configuration.
 *
 * @param columnsInFragmentDefinition - Existing columns definition in the fragment.
 * @param configColumns - Custom columns configuration object.
 * @param fragmentJson - JSON representation of the fragment.
 * @returns Updated columns definition in the fragment.
 */
function maintainExistingColumnInFragment(columnsInFragmentDefinition, configColumns, fragmentJson) {
    if (columnsInFragmentDefinition) {
        //find the right column in the identified fragment file
        if (Array.isArray(columnsInFragmentDefinition)) {
            processCustomColumnInArray(columnsInFragmentDefinition, configColumns);
        }
        else {
            const columnFoundInConfig = handleFragmentColumn(columnsInFragmentDefinition, configColumns);
            if (!columnFoundInConfig) {
                const coreTagName = getTagNameFromFragmentJSON(fragmentJson[exports.FRAGMENT_DEFINITION]);
                if (coreTagName) {
                    delete fragmentJson[exports.FRAGMENT_DEFINITION][coreTagName];
                    columnsInFragmentDefinition = undefined;
                }
            }
        }
    }
    return columnsInFragmentDefinition;
}
/**
 * Method inserts new custom columns into existing columns.
 *
 * @param {v2.TableCustomColumns} configColumns - Custom columns config object.
 * @param {string} fragmentId - fragment file name
 * @param {object} columnsInFragmentDefinition - Existing columns definition
 * @param {ViewTemplateType} viewTemplateType - template type
 * @param {unknown} fragment - fragment definition
 * @param {IdGeneratorFunction} generateId - function to generate ids for new entries in the fragment
 * @returns {object} Columns object.
 */
function insertNewColumnsInFragment(configColumns, fragmentId, columnsInFragmentDefinition, viewTemplateType, fragment, generateId) {
    for (const column of configColumns) {
        if (column.fragmentName.endsWith(fragmentId)) {
            const colPos = configColumns.indexOf(column);
            columnsInFragmentDefinition = insertNewColumnInFragment(column, viewTemplateType, columnsInFragmentDefinition, fragment, colPos, generateId);
        }
    }
    return columnsInFragmentDefinition;
}
/**
 * Actualizes the column information in a fragment.
 *
 * @param fragmentInfo - all necessary information to identify the relevant fragment and column definition.
 * @param fragmentInfo.fragments - list of all fragments
 * @param fragmentInfo.fragmentName - file name of the given fragment, as calculated from the config entry
 * @param fragmentInfo.fragmentId - fragment ID, as calculated from the config entry
 * @param generateId - function to generate ids for new entries in the fragment
 * @param configColumns - list of all custom columns in the config
 * @param viewTemplateType - enum value that determines the view template
 * @returns a boolean value indicating if the fragment was found
 */
function updateColumnsInFragment(fragmentInfo, generateId, configColumns, viewTemplateType) {
    let fragmentFound = false;
    const { fragments, fragmentName, fragmentId } = fragmentInfo;
    if (!fragments) {
        return fragmentFound;
    }
    //find and update the columns' fragment file
    for (const fragment of fragments) {
        if (fragment['dataSourceUri'].endsWith(fragmentName)) {
            let columnsInFragmentDefinition = {};
            fragmentFound = true;
            fragment.changeIndicator = ux_specification_types_1.ChangeIndicator.Updated;
            if (!fragment.fileContent || fragment.fileContent.length === 0) {
                // Empty fragment - use template
                fragment.fileContent = (0, view_controller_generator_1.getColumnFragmentContent)(configColumns, viewTemplateType, generateId);
            }
            else {
                const fragmentJson = JSON.parse((0, xml_js_1.xml2json)(fragment.fileContent, { compact: true }));
                const originalFragmentJson = JSON.stringify(fragmentJson);
                //find the right column in the fragment file
                columnsInFragmentDefinition = getRootCustomColumnFromFragmentJSON(fragmentJson[exports.FRAGMENT_DEFINITION]);
                columnsInFragmentDefinition = maintainExistingColumnInFragment(columnsInFragmentDefinition, configColumns, fragmentJson);
                //Insert scenario for the remaining entries
                columnsInFragmentDefinition = insertNewColumnsInFragment(configColumns, fragmentId, columnsInFragmentDefinition, viewTemplateType, fragmentJson, generateId);
                const tagName = getTagNameFromFragmentJSON(fragmentJson, viewTemplateType);
                fragmentJson[exports.FRAGMENT_DEFINITION][tagName] = columnsInFragmentDefinition;
                const fragmentContent = JSON.stringify(fragmentJson);
                if (fragmentContent !== originalFragmentJson) {
                    fragment.fileContent = (0, xml_js_1.json2xml)(fragmentContent, { compact: true, spaces: 4 });
                }
            }
            break;
        }
    }
    return fragmentFound;
}
/**
 * The function transfers ALL properties of one or more custom columns to a given fragment, or creates a new one if necesary.
 *
 * @param transferParamsV2 - list of input parameters for the recursive function call
 * @param manifestPath - path to the current section of the manifest that describes the extension
 * @param config - current config part, describing the new image of the extension
 * @param viewTemplateType - name of the view template that shall be applied
 */
function exportCustomColumnsToFragment(transferParamsV2, manifestPath, config, viewTemplateType) {
    const { exportResults, appId, logger, idGeneratorFunction } = transferParamsV2;
    const fragments = exportResults.fragments;
    //Find and adapt manifest
    const { manifestSection, lsFilePath, cellsFragmentName, fragmentType } = exportCustomColumnsToManifest(manifestPath, exportResults, config, appId, logger);
    //Find and adapt fragment
    const configColumns = JSON.parse(JSON.stringify(config));
    let fragmentName = manifestSection['fragmentName'];
    const fragmentId = fragmentName.substr(appId.length + 1);
    const fragmentParts = fragmentId.split('.');
    const templateType = fragmentParts[fragmentParts.length - 1];
    fragmentName = templateType + ux_specification_types_1.FRAGMENTNAMEPART + fragmentType;
    const cellFragmentParts = cellsFragmentName?.split('.');
    const cellTemplateType = cellFragmentParts ? cellFragmentParts[cellFragmentParts.length - 1] : null;
    const cellFragmentFileName = cellTemplateType ? cellTemplateType + ux_specification_types_1.FRAGMENTNAMEPART + fragmentType : null;
    // update columns in fragment
    const fragmentFound = updateColumnsInFragment({
        fragments,
        fragmentName,
        fragmentId
    }, idGeneratorFunction, configColumns, viewTemplateType);
    let cellsFragmentFound = false;
    if (cellsFragmentName) {
        //find an update the cells' fragment file
        cellsFragmentFound = updateCellsFragment(fragments, cellFragmentFileName, config, idGeneratorFunction);
    }
    else {
        cellsFragmentFound = true; //not relevant
    }
    if (!fragmentFound) {
        const fragment = {
            fileContent: (0, view_controller_generator_1.getColumnFragmentContent)(configColumns, viewTemplateType, idGeneratorFunction),
            dataSourceUri: lsFilePath,
            changeIndicator: ux_specification_types_1.ChangeIndicator.Deleted
        };
        exportResults.fragments.push(fragment);
    }
    if (!cellsFragmentFound) {
        const fragment = {
            fileContent: (0, view_controller_generator_1.getResponsiveTableCellsFragment)(config, idGeneratorFunction),
            dataSourceUri: lsFilePath.replace(fragmentName, cellFragmentFileName),
            changeIndicator: ux_specification_types_1.ChangeIndicator.Deleted
        };
        exportResults.fragments.push(fragment);
    }
}
/**
 * Determines the manifest path of a column extension.
 *
 * @param page Page object from manifest.
 * @param entitySet Table's entity set.
 * @param [additionalKey] Key provided when defining the FacetID or QuickVariantSelectionX.
 * @param [tableColumnExtensionType] Column extension type.
 * @returns Path to the column extension in the manifest.
 */
const getCustomColumnPath = (page, entitySet, additionalKey, tableColumnExtensionType) => {
    if (!page) {
        return;
    }
    const extension = FE_TEMPLATE_VIEW_EXTENSION_MAP.get(page.component?.name);
    if (!tableColumnExtensionType) {
        let tableType = page.component?.settings?.tableSettings?.['type'];
        if (!tableType) {
            tableType = 'ResponsiveTable';
        }
        if (extension === 'sap.suite.ui.generic.template.AnalyticalListPage.view.AnalyticalListPage') {
            tableType = 'AnalyticalTable';
        }
        tableColumnExtensionType = tableType + 'ColumnsExtension';
    }
    const viewTemplateType = tableColumnExtensionType;
    let extensionKey = `${tableColumnExtensionType}|${entitySet}`;
    if (additionalKey) {
        extensionKey += '|' + additionalKey;
    }
    const path = 'sap.ui5/extends/extensions/sap.ui.viewExtensions/' + extension + '/' + extensionKey;
    return { path, viewTemplateType };
};
exports.getCustomColumnPath = getCustomColumnPath;
//# sourceMappingURL=Fragment.js.map