"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CUSTOM_FIND_TYPES = exports.USER_NAMESPACE_REGEXP = void 0;
exports.repairOverEscapedMablscriptString = repairOverEscapedMablscriptString;
exports.isCustomFindDescriptor = isCustomFindDescriptor;
exports.isCustomFind = isCustomFind;
exports.isCustomFindType = isCustomFindType;
exports.isWaitUntilStep = isWaitUntilStep;
exports.getElementSelectors = getElementSelectors;
exports.getWaitUntilAttributes = getWaitUntilAttributes;
exports.constructWaitUntilXPath = constructWaitUntilXPath;
exports.getWaitUntilSelectors = getWaitUntilSelectors;
exports.reconcileFindOptions = reconcileFindOptions;
exports.getHintsForAssertion = getHintsForAssertion;
exports.maybeGetSourceEventIdentifier = maybeGetSourceEventIdentifier;
exports.translateToMablScript = translateToMablScript;
exports.isLegacyMablscriptFlow = isLegacyMablscriptFlow;
exports.getLegacyFlowIds = getLegacyFlowIds;
const AssertStepTypes_1 = __importDefault(require("./canonical/AssertStepTypes"));
const mablscriptFind_1 = require("@mablhq/test-model/mablscriptFind");
const mablApi_1 = require("../../../mablApi");
exports.USER_NAMESPACE_REGEXP = /^user\./g;
function repairOverEscapedMablscriptString(value) {
    let repaired = value;
    let previous;
    while (repaired !== previous) {
        previous = repaired;
        repaired = repaired.replace(/\\+"/g, '"');
        repaired = (0, mablscriptFind_1.unescapeMablscriptString)(repaired);
    }
    return repaired;
}
exports.CUSTOM_FIND_TYPES = [
    'find_all',
    'find_first',
    'find_last',
    'find_any',
];
function isCustomFindDescriptor(findDescriptor) {
    return !!findDescriptor?.primarySelectors;
}
function isCustomFind(stepWithFind) {
    return !!stepWithFind?.findDescriptor?.primarySelectors;
}
function isCustomFindType(findType) {
    return exports.CUSTOM_FIND_TYPES.includes(findType);
}
function isWaitUntilStep(step) {
    return !!(step.findOptions?.waitUntil &&
        step.stepType === 'assertion' &&
        step.assertionType === AssertStepTypes_1.default.PRESENT);
}
function getElementSelectors(foundElementSelectors) {
    let targetSelector;
    let ancestorSelector;
    if (Array.isArray(foundElementSelectors)) {
        targetSelector = foundElementSelectors[0];
        if (foundElementSelectors.length > 1) {
            ancestorSelector = foundElementSelectors[1];
        }
    }
    else {
        targetSelector = foundElementSelectors;
    }
    return { targetSelector, ancestorSelector };
}
function getWaitUntilAttributes(properties, foundElementSelectors) {
    if (!properties) {
        return { targetAttributes: undefined, ancestorAttributes: undefined };
    }
    const { targetSelector, ancestorSelector } = getElementSelectors(foundElementSelectors);
    const targetAttributes = targetSelector && properties[targetSelector.uuid];
    const ancestorAttributes = ancestorSelector && properties[ancestorSelector.uuid];
    return { targetAttributes, ancestorAttributes };
}
function constructWaitUntilXPath(attributes, elementSelector) {
    if (attributes && elementSelector) {
        let innerTextMatcher;
        const selectorValues = [];
        Object.entries(elementSelector).forEach(([attributeName, attributeValue]) => {
            if (attributes.includes(attributeName)) {
                switch (attributeName) {
                    case 'text':
                        if (elementSelector.text) {
                            innerTextMatcher = mablscriptFind_1.TextAndTagTypeLocator.getInnerTextExpression(elementSelector.text);
                            selectorValues.push(`[${innerTextMatcher} and not(descendant::${elementSelector.tag_name}[${innerTextMatcher}])]`);
                        }
                        break;
                    case 'class_name':
                        attributeValue
                            .split(' ')
                            .forEach((className) => {
                            selectorValues.push(`[contains(@class,"${className}")]`);
                        });
                        break;
                    default:
                        selectorValues.push(`[@${attributeName}="${attributeValue}"]`);
                        break;
                }
            }
        });
        return `//${elementSelector.tag_name}` + selectorValues.join('');
    }
    return undefined;
}
function getWaitUntilSelectors(properties, foundElementSelectors) {
    const { targetAttributes, ancestorAttributes } = getWaitUntilAttributes(properties, foundElementSelectors);
    const { targetSelector, ancestorSelector } = getElementSelectors(foundElementSelectors);
    return {
        targetXPath: constructWaitUntilXPath(targetAttributes, targetSelector),
        ancestorXPath: constructWaitUntilXPath(ancestorAttributes, ancestorSelector),
    };
}
function reconcileFindOptions(selectionType, targetChanged, stepFindOptions, targetFindOptions, hintsFindOptions) {
    if (selectionType !== 'element') {
        return undefined;
    }
    let findOptions;
    if (targetChanged) {
        findOptions = structuredClone(targetFindOptions) || {};
    }
    else {
        findOptions = structuredClone(stepFindOptions) || {};
    }
    findOptions = { ...findOptions, ...(structuredClone(hintsFindOptions) || {}) };
    const findOptionsRecord = findOptions;
    Object.keys(findOptionsRecord).forEach((key) => {
        if (findOptionsRecord[key] &&
            Object.keys(findOptionsRecord[key]).length === 0) {
            delete findOptionsRecord[key];
        }
    });
    if (Object.keys(findOptions).length) {
        return findOptions;
    }
    return undefined;
}
function getHintsForAssertion(selectionType, assertionType) {
    if (selectionType === 'element' &&
        assertionType === AssertStepTypes_1.default.NOT_PRESENT) {
        return { hints: { elementExpectation: 'missing' } };
    }
    return { hints: {} };
}
function maybeGetSourceEventIdentifier(stepPrototype) {
    return stepPrototype.listener && stepPrototype.sourceEventTimeStamp
        ? `${stepPrototype.listener}-${stepPrototype.sourceEventTimeStamp}`
        : undefined;
}
function maybeGetCommentSymbol(disabled) {
    return disabled ? '//' : '';
}
function translateToMablScript(mablscriptSteps) {
    return mablscriptSteps
        .filter((mablscriptAction) => mablscriptAction.willGenerateMablscript())
        .reduce((mablscript, mablscriptAction) => mablscript +
        maybeGetCommentSymbol(mablscriptAction.disabled) +
        mablscriptAction.generateMablscript() +
        '\n', '');
}
function isLegacyMablscriptFlow(flow) {
    if (flow.flow_type !== mablApi_1.FlowTypeEnum.Mablscript) {
        return false;
    }
    const hasScript = !!flow.script;
    const hasJsonSteps = flow.json_steps?.steps && flow.json_steps.steps.length > 0;
    return hasScript && !hasJsonSteps;
}
function getLegacyFlowIds(flows) {
    return flows
        .filter(isLegacyMablscriptFlow)
        .map((flow) => flow.id)
        .filter((id) => !!id);
}
