"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.addPatternForBindingChangeOfEnumOPV4 = exports.addPatternForBindingChangeOfEnumOP = exports.addPatternForBindingChangeOfEnumLR = exports.getActionBreadcrumbParts = exports.buildColumnControlId = exports.BindingValueV4 = exports.BindingValue = exports.convertSectionId = exports.buildControlIdForPage = exports.buildControlIdFromParent = void 0;
exports.escapeId = escapeId;
exports.doNotDelete = doNotDelete;
const ux_specification_types_1 = require("@sap/ux-specification-types");
const utils_1 = require("../utils");
/**
 * General export rule, joining all given breadcrumbs to the base ID.
 *
 * @param baseId - base ID, first part of the stable ID
 * @param idBreadcrumbs - array of ID parts
 * @returns the constructed stable ID as a string
 */
const buildControlIdFromParent = (baseId, idBreadcrumbs) => {
    return baseId + idBreadcrumbs.join('::');
};
exports.buildControlIdFromParent = buildControlIdFromParent;
/**
 * Constructs a stable ID for pages by combining the base ID, ID breadcrumbs, and the first breadcrumb.
 *
 * @param baseId - base ID, first part of the stable ID
 * @param idBreadcrumbs - array of ID parts
 * @param breadcrumbs - array of breadcrumbs
 * @returns the constructed stable ID as a string
 */
const buildControlIdForPage = (baseId, idBreadcrumbs, breadcrumbs) => {
    return baseId + idBreadcrumbs.join('::') + breadcrumbs[0];
};
exports.buildControlIdForPage = buildControlIdForPage;
/**
 * Converts the section id to the right string for the stable id:
 * If the corresponding facet has ID maintained, we must take this ID. If ID is not present, take the navigation path.
 *
 * @param sectionId - old ID that shall get converted
 * @param title - title from JSON schema, comprising the facet ID
 * @returns the converted section ID as a string
 */
const convertSectionId = (sectionId, title) => {
    let convertedSectionId;
    const prefix = ux_specification_types_1.FACETTITLEPREFIX;
    if (title !== undefined && title.includes(prefix)) {
        convertedSectionId = title.split(prefix)[1];
    }
    else {
        convertedSectionId = sectionId.replace(new RegExp('/@', 'g'), '::').replace(/@com.sap/g, 'com.sap');
    }
    return convertedSectionId;
};
exports.convertSectionId = convertSectionId;
/**
 * Escapes all characters not allowed in stable IDs with a colon followed by their hexadecimal code.
 *
 * @param sParam - The string to be escaped.
 * @returns The escaped string.
 */
function escapeId(sParam) {
    /* escape all characters not allowed in stable ids with :<hexcode>
     * as we use : as escape character, also escape :
     */
    return sParam.replace(/[^-A-Za-z0-9_.:]/g, function (c) {
        const sCode = c.charCodeAt(0).toString(16);
        return `:${sCode.length === 1 ? '0' : ''}${sCode}`;
    });
}
/**
 * V2 - Binding Change values, will be added on object pages
 */
var BindingValue;
(function (BindingValue) {
    BindingValue["Editable"] = "{ui>/editable}";
    BindingValue["NotEditable"] = "{= !${ui>/editable}}";
})(BindingValue || (exports.BindingValue = BindingValue = {}));
/**
 * V4 - Binding Change values, will be added on object pages
 */
var BindingValueV4;
(function (BindingValueV4) {
    BindingValueV4["Editable"] = "{= ${ui>/editMode} === 'Editable'}";
    BindingValueV4["NotEditable"] = "{= ${ui>/editMode} !== 'Editable'}";
})(BindingValueV4 || (exports.BindingValueV4 = BindingValueV4 = {}));
/**
 * Consolidates the list of id's and other breadcrumbs into one list, for finding the right stable ID of a column.
 *
 * @param idBreadcrumbs - array of ID parts
 * @param localBreadcrumbs - array of breadcrumbs
 * @param title - (section) title = facet ID
 * @returns the consolidated breadcrumbs' list
 */
function mapBreadcrumbs(idBreadcrumbs, localBreadcrumbs, title) {
    let sectionId;
    idBreadcrumbs = idBreadcrumbs.map(function (item) {
        if (item === ux_specification_types_1.PropertyName.sections) {
            for (let index = 0; index < localBreadcrumbs.length; index++) {
                const breadcrumb = localBreadcrumbs[index];
                if (breadcrumb === ux_specification_types_1.PropertyName.sections) {
                    sectionId = localBreadcrumbs[index + 1];
                    localBreadcrumbs[index + 1] = (0, exports.convertSectionId)(sectionId, title) + '::Table';
                    return localBreadcrumbs[index + 1];
                }
            }
        }
        return item;
    });
    return { idBreadcrumbs };
}
/**
 * Export rule for table columns.
 *
 * @param baseId - base ID, first part of the stable ID. Represents the stableId of the table.
 * @param idBreadcrumbs - array of ID parts, these are ID's that had been calculated on higher levels of the hierarchy
 * @param breadcrumbs - array of breadcrumbs, i.e. the path elements to the column in the config file
 * @param _controlType - controlType function of decorators, not used here
 * @param title - title from JSON schema, comprising the facet ID
 * @returns the constructed stable ID as a string
 */
const buildColumnControlId = (baseId, idBreadcrumbs, breadcrumbs, _controlType, title) => {
    let tableId = 'listReport'; //default
    const localBreadcrumbs = [...breadcrumbs];
    ({ idBreadcrumbs } = mapBreadcrumbs(idBreadcrumbs, localBreadcrumbs, title));
    if (localBreadcrumbs[0] === ux_specification_types_1.PropertyName.sections) {
        //special handling for section tables
        tableId = localBreadcrumbs[1]
            .replace(/::com.sap.vocabularies/g, ux_specification_types_1.VOCWITHSLASH)
            .replace(/::@com.sap.vocabularies/g, ux_specification_types_1.VOCWITHSLASH);
    }
    else if (idBreadcrumbs[0] === ux_specification_types_1.PropertyName.table) {
        tableId = idBreadcrumbs[0];
    }
    const columnId = localBreadcrumbs[localBreadcrumbs.length - 1];
    let encodedColumnId = columnId
        .replace(/::com.sap.vocabularies/g, ux_specification_types_1.VOCWITHSLASH)
        .replace(/::@com.sap.vocabularies/g, ux_specification_types_1.VOCWITHSLASH)
        .replace('sTarget/@', 'sTarget::@');
    let fullId;
    const splitPoint = encodedColumnId.indexOf(':::');
    if (encodedColumnId.startsWith('DataField') && splitPoint > -1) {
        //DataFieldForAction, DataFieldWithIntentBasedNavigation, DataFieldWithNavigationPath, ...
        encodedColumnId = encodedColumnId.replace('/', ':2f');
        fullId = `${baseId}template:::TableColumn:::${encodedColumnId.substring(0, splitPoint)}:::sSmartTableId::${tableId.replace('::Table', ':3a:3aTable')}:::${encodedColumnId.substring(splitPoint + 3)}`;
    }
    else {
        //Columns of type DataField, they do not have any DataField::: prefix
        //==> legacy encoding, for smart table columns only
        encodedColumnId = encodedColumnId.replace('/', '_');
        fullId = `${baseId}${idBreadcrumbs.join('::')}-${encodedColumnId}`;
    }
    return escapeId(fullId);
};
exports.buildColumnControlId = buildColumnControlId;
/**
 * Split up action breadcrumb and return different parts from it.
 *
 * @param breadcrumbs - array of breadcrumbs
 * @returns {object} - actionType, semanticObjectId, actionId of action
 */
const getActionBreadcrumbParts = (breadcrumbs) => {
    const actionIdParts = breadcrumbs[breadcrumbs.length - 1].split(':::');
    let actionType, semanticObjectId, actionId;
    if (actionIdParts.length > 2) {
        actionType = actionIdParts[0];
        semanticObjectId = actionIdParts[1].split('::')[1];
        actionId = actionIdParts[2].split('::')[1];
    }
    else if (actionIdParts.length === 2) {
        actionType = actionIdParts[0];
        actionId = actionIdParts[1].split('sAction::')[1];
    }
    else {
        actionId = actionIdParts[0];
    }
    return { actionType, semanticObjectId, actionId };
};
exports.getActionBreadcrumbParts = getActionBreadcrumbParts;
/**
 * Determines the valid pattern for a binding change.
 *
 * @param schemaDefinition - definition in the JSON schema
 * @returns the pattern as string
 */
function determinePattern(schemaDefinition) {
    let pattern = ux_specification_types_1.BINDINGPROPERTYREGEXSTRING;
    if (schemaDefinition.enum) {
        let enumPattern;
        schemaDefinition.enum.forEach((enumValue) => {
            if (!enumValue.toString().startsWith('{')) {
                enumPattern = enumPattern ? `${enumPattern}|${enumValue.toString()}` : enumValue.toString();
            }
        });
        pattern = `^(${enumPattern})$|${pattern}`;
    }
    if (schemaDefinition['type'] && schemaDefinition['type'] === 'boolean') {
        pattern = `^(false|true)$|${pattern}`;
    }
    return pattern;
}
/**
 * Reuseable function for strings that allow binding changes.
 *
 * @param schema - the complete JSON schema
 * @param definition - definition in the JSON schema, to be updated
 * @param propertyName - property in the properties' list of the given definition
 * @param bindingValues - values that shall be added to the resulting enum
 */
const addPatternForBindingChangeOfEnum = (schema, definition, propertyName, bindingValues) => {
    const propertyList = definition && definition['properties'];
    if (propertyList[propertyName].pattern) {
        return; //as already processed
    }
    const originalDefinition = propertyList[propertyName];
    let resultDefinition = originalDefinition;
    const targetDefinition = originalDefinition.$ref
        ? schema['definitions'][originalDefinition.$ref.split(utils_1.DEFINITION_LINK_PREFIX)[1]]
        : originalDefinition;
    const description = originalDefinition.description ? originalDefinition.description : targetDefinition.description;
    const pattern = determinePattern(targetDefinition);
    if (targetDefinition['type'] && targetDefinition['type'] === 'boolean') {
        //Always an enum, always with more than one value
        resultDefinition = { enum: [false, true] };
    }
    if (bindingValues && resultDefinition['enum']) {
        bindingValues.forEach((value) => {
            if (resultDefinition['enum'].indexOf(value) === -1) {
                resultDefinition['enum'].push(value);
            }
        });
    }
    propertyList[propertyName] = {
        pattern: pattern,
        anyOf: [
            resultDefinition,
            {
                type: 'string'
            }
        ]
    };
    if (description) {
        propertyList[propertyName].description = description;
        delete originalDefinition.description;
    }
};
const addPatternForBindingChangeOfEnumLR = (schema, definition, propertyName) => {
    addPatternForBindingChangeOfEnum(schema, definition, propertyName);
};
exports.addPatternForBindingChangeOfEnumLR = addPatternForBindingChangeOfEnumLR;
const addPatternForBindingChangeOfEnumOP = (schema, definition, propertyName) => {
    const bindingValues = Object.values(BindingValue);
    addPatternForBindingChangeOfEnum(schema, definition, propertyName, bindingValues);
};
exports.addPatternForBindingChangeOfEnumOP = addPatternForBindingChangeOfEnumOP;
const addPatternForBindingChangeOfEnumOPV4 = (schema, definition, propertyName) => {
    const bindingValues = Object.values(BindingValueV4);
    addPatternForBindingChangeOfEnum(schema, definition, propertyName, bindingValues);
};
exports.addPatternForBindingChangeOfEnumOPV4 = addPatternForBindingChangeOfEnumOPV4;
/**
 * Sync rule for preventing the deletion of a property.
 */
function doNotDelete() {
    return;
}
//# sourceMappingURL=control.js.map