"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertXmlFileToConfig = convertXmlFileToConfig;
exports.createCustomPageConfig = createCustomPageConfig;
exports.createCustomFragmentConfig = createCustomFragmentConfig;
const utils_1 = require("../../utils/utils");
const macros_1 = require("../../utils/macros");
/**
 * Method checks if passed string value and schema matches to boolean type.
 *
 * @param {string} value Attribute value from xml file.
 * @param {SchemaDefinition} schema Property's schema containing information about property type.
 * @returns {boolean} Is value a boolean type.
 */
function isBoolean(value, schema) {
    const schemaBoolean = 'boolean';
    if (schema.type === schemaBoolean ||
        schema.anyOf?.find((entry) => entry.type === schemaBoolean)) {
        return value === 'true' || value === 'false';
    }
    return false;
}
/**
 * Method checks if passed string value and schema matches to number type.
 *
 * @param {string} value Attribute value from xml file.
 * @param {SchemaDefinition} schema Property's schema containing information about property type.
 * @returns {boolean} Is value a number type.
 */
function isNumber(value, schema) {
    const schemaNumber = 'number';
    if (schema.type === schemaNumber || schema.anyOf?.find((entry) => entry.type === schemaNumber)) {
        return !isNaN(parseFloat(value.toString()));
    }
    return false;
}
/**
 * Method converts string value from XML file attribute to strict type depending on property's schema.
 *
 * @param {string | number} value Attribute value from xml file.
 * @param {SchemaDefinition} schema Property's schema containing information about property type.
 * @returns {unknown} Converted value.
 */
function convertValue(value, schema) {
    const valueStr = value.toString();
    if (isBoolean(valueStr, schema)) {
        return valueStr === 'true' ? true : false;
    }
    if (isNumber(valueStr, schema)) {
        return parseFloat(valueStr);
    }
    return value;
}
/**
 * Callback method of traversing schema and XML.
 * Method imports value from XML element to page config object.
 *
 * @param {TraverseData} traverseData Schema and XML traverse data.
 * @param {SchemaDefinition} property Schema property to use for import.
 * @param {object} config Fragment of page config object.
 * @param {string} name Name of property to import.
 * @returns {boolean} Is new value differs.
 */
function importProperty(traverseData, property, config, name) {
    const { element } = traverseData;
    let differs = false;
    // Do not import comments inside XML
    if (element && element.type !== 'comment' && element.attributes && name in element.attributes) {
        const value = convertValue(element.attributes[name], property);
        if (value !== config[name]) {
            config[name] = value;
            differs = true;
        }
    }
    if (property.isViewNode && property.metadata?.overrideClass && element?.elements) {
        const overrideClass = property.metadata.overrideClass;
        const shortName = overrideClass.slice(overrideClass.lastIndexOf('.') + 1);
        const overrideEl = (0, macros_1.findChildElementByLocalNameAndKey)(element, shortName, name);
        if (overrideEl?.attributes) {
            const props = property.properties ?? {};
            const override = {};
            for (const [k, v] of Object.entries(overrideEl.attributes)) {
                if (k !== 'key' && v !== undefined) {
                    override[k] = props[k]
                        ? convertValue(v, props[k])
                        : v;
                }
            }
            if (Object.keys(override).length) {
                config[name] = { ...(config[name] ?? {}), ...override };
                differs = true;
            }
        }
    }
    return differs;
}
/**
 * Method coverts xml file with json schema to page config.
 *
 * @param {ExtensionFileData} fileData XML file data.
 * @param {SchemaDefinition} schema Schema of target config.
 * @param {ExtensionLogger} logger Logger.
 * @returns {PageConfig} Converted config.
 */
function convertXmlFileToConfig(fileData, schema, logger) {
    let config;
    const element = (0, macros_1.parseXML)(fileData.file, false, logger);
    if (element) {
        const coreElement = (0, macros_1.getRootElement)(element);
        config = {};
        // get schema definition for passed fragment
        (0, macros_1.traverseSchema)({
            fullSchema: schema,
            schema: schema,
            element: coreElement,
            contextPath: [],
            config
        }, importProperty);
    }
    return config;
}
/**
 * Imports the content of fpm custom page by parsing associated view file.
 *
 * @param {ImportFPMCustomPageV4Parameters} importParameters Object comprising all input data.
 * @returns {v4.ListReportConfigV4 | undefined} Result of import.
 */
function createCustomPageConfig(importParameters) {
    const { views, manifest, jsonSchema, routingId, logger } = importParameters;
    if (!jsonSchema || Object.keys(jsonSchema).length === 0) {
        // Unsupported feature
        return undefined;
    }
    const viewData = (0, utils_1.getPageCustomViewFile)(views || [], routingId, manifest, logger);
    let config;
    if (viewData) {
        config = convertXmlFileToConfig(viewData, jsonSchema, importParameters.logger);
    }
    return config;
}
/**
 * Imports the content of fpm custom page by parsing associated fragment file.
 *
 * @param {ImportObjectPageV4Parameters} importParameters Object comprising all input data.
 * @param {string} fragmentName Fragment full namespace.
 * @returns {v4.ListReportConfigV4 | undefined} Result of import.
 */
function createCustomFragmentConfig(importParameters, fragmentName) {
    const { fragments, manifest, jsonSchema, routingId, logger } = importParameters;
    const definitionKey = (0, macros_1.getCustomExtensionFragmentDefinitionKey)(fragmentName);
    const schema = jsonSchema['definitions']?.[definitionKey];
    if (!jsonSchema || !schema) {
        // Unsupported feature
        return undefined;
    }
    const targetManifest = (0, utils_1.getManifestPage)(manifest, routingId);
    const fragmentData = (0, utils_1.getPageCustomExtensionFile)(fragments || [], targetManifest, manifest, 'fragment', fragmentName);
    let config;
    if (fragmentData) {
        const tempSchema = {
            ...schema,
            definitions: jsonSchema['definitions']
        };
        config = convertXmlFileToConfig(fragmentData, tempSchema, logger);
    }
    return config;
}
//# sourceMappingURL=fpmCustomPage.js.map