"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.macrosHandlers = void 0;
exports.applyOverrideClasses = applyOverrideClasses;
const ux_specification_types_1 = require("@sap/ux-specification-types");
const listReport_1 = require("../list-report/listReport");
const common_1 = require("../../../common");
const utils_1 = require("./utils");
const utils_2 = require("../../utils/utils");
/**
 * Method resolves passed "metaPath" property from XML node.
 *
 * @param {string} metaPath "metaPath" property from XML node.
 * @returns {MetaPathResolution} Meta path resolution.
 */
function resolveMetaPath(metaPath) {
    const metaPathParts = metaPath.split('/');
    const pathParts = [];
    let term;
    for (const metaPathPart of metaPathParts) {
        if (metaPathPart) {
            if (metaPathPart.startsWith('@')) {
                term = metaPathPart;
                break;
            }
            pathParts.push(metaPathPart);
        }
    }
    if (pathParts.length) {
        return {
            path: pathParts.join('/'),
            term
        };
    }
    return { term: metaPath };
}
/**
 * Method returns entity type for passed macros annotation handler params.
 *
 * @param {HandlerParams} params Macros annotation handler params containing serviceAvt and connection context information.
 * @returns {EntityType | undefined} EntityType for passed connection.
 */
function getEntityTypeResolution(params) {
    const { node, serviceAVT, connectionContext } = params;
    const contextPath = (0, utils_1.getAttribute)(node, 'contextPath') || connectionContext.contextPath;
    let metaPath = (0, utils_1.getAttribute)(node, 'metaPath');
    const entitySet = connectionContext.entitySet;
    const isAbsoluteMetaPath = metaPath?.startsWith('/');
    if (!contextPath && !entitySet && !isAbsoluteMetaPath) {
        return undefined;
    }
    let path = contextPath || `/${entitySet}`;
    if (metaPath) {
        const metaPathResolution = resolveMetaPath(metaPath);
        if (metaPathResolution.path) {
            path = isAbsoluteMetaPath ? metaPathResolution.path : `${path}/${metaPathResolution.path}`;
            metaPath = metaPathResolution.term;
        }
    }
    const resolvedContextPath = serviceAVT?.resolvePath(path);
    let entityType;
    switch (resolvedContextPath?.target?.['_type']) {
        case 'EntitySet': {
            entityType = resolvedContextPath.target.entityType;
            break;
        }
        case 'NavigationProperty': {
            entityType = resolvedContextPath.target.targetType;
            break;
        }
        case 'EntityType': {
            entityType = resolvedContextPath.target;
            break;
        }
    }
    // Resolve qualifier
    let qualifier;
    const qualiferParts = metaPath.split('#');
    if (qualiferParts.length) {
        qualifier = qualiferParts[1];
    }
    // Annotation key in "vocabularies" annotations
    let annotationKey = undefined;
    if (metaPath) {
        const keyParts = metaPath.split('.');
        if (keyParts.length) {
            annotationKey = keyParts[keyParts.length - 1];
        }
    }
    return entityType
        ? {
            entityType,
            metaPath,
            qualifier,
            annotationKey
        }
        : undefined;
}
/**
 * Method applies annotation path for passed XML node's schema.
 *
 * @param {HandlerParams} schema Schema to update with "annotationPath".
 * @param {EntityTypeResolution} [entityTypeResolution] Entity type resolution object.
 */
function applyAnnotationPath(schema, entityTypeResolution) {
    if (entityTypeResolution?.metaPath) {
        const { entityType, metaPath } = entityTypeResolution;
        schema.annotationPath = `/${entityType.fullyQualifiedName}/${metaPath}`;
    }
}
/**
 * Method returns data for table annotation line items for passed entity type resolution.
 *
 * @param {EntityTypeResolution} entityTypeResolution Entity type resolution object.
 * @param {ConvertedMetadata} serviceAVT Combined service metadata, as returned by annotation vocabularies tools.
 * @param {ConvertedMetadata} alias Annotation alias.
 * @returns {AnnotationPathData | undefined} Table annotation line items.
 */
function getDirectAnnotationPath(entityTypeResolution, serviceAVT, alias) {
    const { metaPath, entityType } = entityTypeResolution;
    let term;
    let annotationPath;
    if (entityType && metaPath) {
        const annotation = (0, listReport_1.analyzeViewAnnotation)(metaPath, entityType?.annotations?.[alias], serviceAVT);
        if (annotation.visualization) {
            const annotationTerm = annotation.visualization.split('.')[1];
            term = entityType?.annotations?.[alias]?.[annotationTerm];
            if (term?.fullyQualifiedName) {
                annotationPath = (0, common_1.getAnnotationPathUsingFullyQualifiedName)(entityType, term.fullyQualifiedName);
            }
        }
    }
    if (term) {
        return {
            term,
            annotationPath
        };
    }
    return undefined;
}
const AGGREGATION_OVERRIDE_CLASS_MAP = new Map([
    ['columns', 'sap.fe.macros.table.ColumnOverride'],
    ['actions', 'sap.fe.macros.table.ActionOverride']
]);
/**
 * Applies properties from an override class definition to all annotation-based controls in an aggregation.
 *
 * Annotation-based controls (those with an `annotationPath`) can be configured via override elements
 * (e.g. `ColumnOverride`, `ActionOverride`) in the view XML. This method injects the override class's
 * properties into each annotation control's schema entry so the IDE properties panel can display them,
 * without creating separate schema nodes.
 *
 * @param controlsSchema Schema of the controls aggregation (e.g. `columns` or `actions`).
 * @param aggregationName Name of the aggregation — determines which override class to apply.
 * @param schema Full BuildingBlocks schema, used to look up the override class definition.
 */
function applyOverrideClasses(controlsSchema, aggregationName, schema) {
    if (typeof controlsSchema !== 'object') {
        return;
    }
    const overrideClassName = AGGREGATION_OVERRIDE_CLASS_MAP.get(aggregationName);
    if (!overrideClassName) {
        return;
    }
    const definition = schema.definitions?.[overrideClassName];
    if (!definition?.properties) {
        return;
    }
    const filtered = {};
    for (const [k, v] of Object.entries(definition.properties)) {
        if (k !== 'key' && typeof v === 'object' && !v.metadata?.path?.length) {
            filtered[k] = v;
        }
    }
    for (const controlSchema of Object.values(controlsSchema.properties ?? {})) {
        if (!controlSchema || typeof controlSchema !== 'object' || !('annotationPath' in controlSchema)) {
            continue;
        }
        const schemaDef = controlSchema;
        schemaDef.properties = JSON.parse(JSON.stringify(filtered));
        schemaDef.metadata = { ...schemaDef.metadata, overrideClass: overrideClassName };
    }
}
// Handlers map for macros controls
exports.macrosHandlers = {
    'sap.fe.macros.Chart': (params) => {
        const { schema, serviceAVT } = params;
        const entityTypeResolution = getEntityTypeResolution(params);
        applyAnnotationPath(schema, entityTypeResolution);
        if (schema.annotationPath) {
            const alias = (0, common_1.findAlias)(ux_specification_types_1.UIVOCABULARY, serviceAVT);
            const annotationData = getDirectAnnotationPath(entityTypeResolution, serviceAVT, alias);
            if (annotationData?.annotationPath) {
                params.schema.annotationPath = annotationData.annotationPath;
            }
        }
    },
    'sap.fe.macros.Form': (params) => {
        const { schema, serviceAVT, rootSchema } = params;
        const entityTypeResolution = getEntityTypeResolution(params);
        applyAnnotationPath(schema, entityTypeResolution);
        // Populate fields.properties with DataField entries from the FieldGroup annotation
        const fieldsDefinition = schema.properties?.fields;
        if (typeof fieldsDefinition === 'object' && entityTypeResolution?.annotationKey && schema.annotationPath) {
            if (!fieldsDefinition.properties) {
                fieldsDefinition.properties = {};
            }
            const alias = (0, common_1.findAlias)(ux_specification_types_1.UIVOCABULARY, serviceAVT);
            const fieldGroupAnnotation = alias && entityTypeResolution.entityType?.annotations?.[alias]?.[entityTypeResolution.annotationKey];
            if (fieldGroupAnnotation?.Data) {
                const dataForFieldGroup = {
                    isObjectPage: false,
                    isMacro: true,
                    appSchema: rootSchema,
                    lineItemAnnotation: fieldGroupAnnotation.Data,
                    entityType: entityTypeResolution.entityType,
                    oDataServiceAVT: serviceAVT,
                    lineItemId: ''
                };
                (0, utils_2.appendLineItemsToSchema)(dataForFieldGroup, fieldsDefinition, `${schema.annotationPath}/Data`, fieldsDefinition);
            }
        }
    },
    'sap.fe.macros.FilterBar': (params) => {
        const { schema, serviceAVT, rootSchema } = params;
        const entityTypeResolution = getEntityTypeResolution(params);
        // Handler selection fields
        const filterFieldsDefinition = schema.properties?.filterFields;
        if (typeof filterFieldsDefinition === 'object' && entityTypeResolution?.annotationKey) {
            if (!filterFieldsDefinition.properties) {
                filterFieldsDefinition.properties = {};
            }
            const alias = (0, common_1.findAlias)(ux_specification_types_1.UIVOCABULARY, serviceAVT);
            const selectionFieldAnnotation = alias && entityTypeResolution.entityType?.annotations?.[alias]?.[entityTypeResolution.annotationKey];
            (0, listReport_1.addSelectionFields)(entityTypeResolution.entityType, rootSchema, selectionFieldAnnotation, filterFieldsDefinition, entityTypeResolution.qualifier);
        }
    },
    'sap.fe.macros.Table': (params) => {
        const { schema, serviceAVT, rootSchema } = params;
        const entityTypeResolution = getEntityTypeResolution(params);
        const colDefinition = schema.properties?.columns;
        const actionDefinition = schema.properties?.actions;
        if (typeof colDefinition === 'object' && typeof actionDefinition === 'object' && entityTypeResolution) {
            if (!colDefinition.properties) {
                colDefinition.properties = {};
            }
            if (!actionDefinition.properties) {
                actionDefinition.properties = {};
            }
            const alias = (0, common_1.findAlias)(ux_specification_types_1.UIVOCABULARY, serviceAVT);
            applyAnnotationPath(schema, entityTypeResolution);
            if (schema.annotationPath) {
                const annotationData = getDirectAnnotationPath(entityTypeResolution, serviceAVT, alias);
                if (annotationData?.annotationPath) {
                    schema.annotationPath = annotationData.annotationPath;
                }
                const dataForLineItem = {
                    isObjectPage: false,
                    appSchema: rootSchema,
                    lineItemAnnotation: annotationData.term,
                    entityType: entityTypeResolution.entityType,
                    oDataServiceAVT: serviceAVT,
                    lineItemId: ux_specification_types_1.DefinitionName.LineItems,
                    isMacro: true
                };
                (0, utils_2.appendLineItemsToSchema)(dataForLineItem, actionDefinition, schema.annotationPath, colDefinition);
                applyOverrideClasses(colDefinition, 'columns', rootSchema);
                applyOverrideClasses(actionDefinition, 'actions', rootSchema);
            }
        }
    },
    'sap.fe.macros.richtexteditor.ButtonGroup': (params) => {
        const { node, schema } = params;
        const customToolBarPriority = (0, utils_1.getAttribute)(node, 'customToolbarPriority');
        if (customToolBarPriority !== undefined) {
            // Set propertyIndex for UI ordering based on customToolbarPriority attribute
            schema.propertyIndex = Number(customToolBarPriority);
        }
    }
};
//# sourceMappingURL=annotations.js.map