"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.createVariableStepWithUpdatedReusableSnippet = createVariableStepWithUpdatedReusableSnippet;
exports.isCreateVariableStepInstance = isCreateVariableStepInstance;
exports.humanizeCreateVariableStep = humanizeCreateVariableStep;
exports.createVariableStepToAIString = createVariableStepToAIString;
const dom_util_1 = require("@mablhq-internal/mablscript-find/dom-util");
const mablscriptFind_1 = require("@mablhq/test-model/mablscriptFind");
const JavaScriptAction_1 = require("@mablhq/test-model/actions/JavaScriptAction");
const SnippetsDescriptor_1 = require("@mablhq/test-model/types/SnippetsDescriptor");
const mablscript_step_types_1 = require("../../mablscript-step-types");
const snippetUtils_1 = require("../snippetUtils");
const type_utils_1 = require("../../type-utils");
const variable_utils_1 = require("../../variable-utils");
const variable_constants_1 = require("../../variable-constants");
const variable_names_util_1 = require("../../variable-names-util");
const StepWithFind_1 = __importStar(require("./StepWithFind"));
const yaml_utils_1 = require("../yaml-utils");
const CreateVariableMobileStep_1 = require("@mablhq/test-model/mobile/steps/CreateVariableMobileStep");
const CreateVariableStepDescriptor_1 = require("@mablhq/test-model/types/CreateVariableStepDescriptor");
const FindAction_1 = require("@mablhq/test-model/actions/FindAction");
const ExtractAction_1 = require("@mablhq/test-model/actions/ExtractAction");
const EvaluateJSStep_1 = require("./EvaluateJSStep");
const MablStepV2_1 = require("@mablhq/test-model/MablStepV2");
class CreateVariableStep extends StepWithFind_1.default {
    static getStepType() {
        return mablscript_step_types_1.StepType.CREATE_VARIABLE;
    }
    static isEditable(variable) {
        return (!!variable &&
            (variable.variableType !== mablscriptFind_1.VariableType.JAVASCRIPT ||
                !!variable.snippet));
    }
    constructor(variable, findDescriptor, findOptions) {
        super(CreateVariableStep.getStepType(), findDescriptor, findOptions);
        this.variable = variable;
        this.mergeOptions({ editable: CreateVariableStep.isEditable(variable) });
        if (variable?.variableType === mablscriptFind_1.VariableType.MABL_MAILBOX) {
            this.mergeOptions({ feature: StepWithFind_1.MAILBOX_FEATURE });
        }
    }
    getSnippetInvariantId() {
        return getSnippetInvariantId(this);
    }
    generateMablscript() {
        let predicateAction;
        switch (this.variable.variableType) {
            case mablscriptFind_1.VariableType.GENERATED:
                predicateAction = `generate_random_string("${(0, mablscriptFind_1.escapeMablscriptString)(this.variable.pattern)}")`;
                break;
            case mablscriptFind_1.VariableType.ELEMENT_PROPERTY: {
                predicateAction = `${this.findDescriptorToMablscript()}.extract_attribute("${this.variable.property}")`;
                break;
            }
            case mablscriptFind_1.VariableType.JAVASCRIPT: {
                const evaluateJsAction = JavaScriptAction_1.JavaScriptAction.fromDescriptor({
                    javaScript: this.variable.javaScript,
                });
                predicateAction = evaluateJsAction.toMablscript();
                break;
            }
            case mablscriptFind_1.VariableType.MABL_MAILBOX:
                predicateAction = `generate_email_address()`;
                break;
            case mablscriptFind_1.VariableType.ELEMENT_COUNT:
                predicateAction = `${this.findDescriptorToMablscript()}.count()`;
                break;
            case mablscriptFind_1.VariableType.COOKIE:
                predicateAction = `${this.findDescriptorToMablscript()}.extract_attribute("${this.variable.property}")`;
                break;
        }
        if (predicateAction) {
            return `${predicateAction}.as("${this.variable.humanizedName}")`;
        }
        throw new Error('Invalid step; mablscript cannot be generated.');
    }
    generateMobileCliStep() {
        let step;
        switch (this.variable.variableType) {
            case mablscriptFind_1.VariableType.GENERATED:
                step = new CreateVariableMobileStep_1.CreateVariableMobileStep({
                    disabled: this.disabled,
                    generator: {
                        pattern: this.variable.pattern,
                        type: CreateVariableStepDescriptor_1.VariableGenerator.PATTERN,
                    },
                    name: this.variable.humanizedName,
                });
                break;
            case mablscriptFind_1.VariableType.ELEMENT_PROPERTY:
                {
                    const findDescriptor = {
                        findOptions: this.findOptions,
                        findTarget: this.findDescriptor,
                        findType: this.findDescriptor.type,
                    };
                    step = new CreateVariableMobileStep_1.CreateVariableMobileStep({
                        disabled: this.disabled,
                        find: findDescriptor,
                        generator: {
                            attribute: this.variable.property,
                            type: CreateVariableStepDescriptor_1.VariableGenerator.ATTRIBUTE,
                        },
                        name: this.variable.humanizedName,
                    });
                }
                break;
            case mablscriptFind_1.VariableType.JAVASCRIPT:
                {
                    step = new CreateVariableMobileStep_1.CreateVariableMobileStep({
                        disabled: this.disabled,
                        generator: {
                            javaScript: this.variable.javaScript,
                            type: CreateVariableStepDescriptor_1.VariableGenerator.JAVASCRIPT,
                        },
                        name: this.variable.humanizedName,
                    });
                }
                break;
            case mablscriptFind_1.VariableType.MABL_MAILBOX:
                step = new CreateVariableMobileStep_1.CreateVariableMobileStep({
                    disabled: this.disabled,
                    generator: {
                        type: CreateVariableStepDescriptor_1.VariableGenerator.EMAIL,
                    },
                    name: this.variable.humanizedName,
                });
                break;
            case mablscriptFind_1.VariableType.ELEMENT_COUNT:
                step = new CreateVariableMobileStep_1.CreateVariableMobileStep({
                    disabled: this.disabled,
                    find: this.findDescriptor,
                    generator: {
                        type: CreateVariableStepDescriptor_1.VariableGenerator.ELEMENT_COUNT,
                    },
                    name: this.variable.humanizedName,
                });
                break;
            default:
                throw new Error(`Invalid variable type in switch; CreateVariableMobileStep cannot be generated.`);
        }
        if (!this.id) {
            this.generateStepId();
        }
        if (this.id) {
            step.setStepId(this.id);
        }
        return step;
    }
    inputVariables() {
        switch (this.variable.variableType) {
            case mablscriptFind_1.VariableType.GENERATED:
                return (0, type_utils_1.distinct)((0, variable_names_util_1.extractVariableNamesFromPattern)(this.variable.pattern));
            case mablscriptFind_1.VariableType.ELEMENT_PROPERTY:
            case mablscriptFind_1.VariableType.ELEMENT_COUNT:
                return super.inputVariables();
            case mablscriptFind_1.VariableType.JAVASCRIPT: {
                if ((0, SnippetsDescriptor_1.isInlineSnippetDescriptor)(this.variable.javaScript) ||
                    (0, SnippetsDescriptor_1.isReusableSnippetDescriptor)(this.variable.javaScript) ||
                    (0, snippetUtils_1.getResolvedSnippetParameters)(this) !== undefined) {
                    return (0, snippetUtils_1.getVariableReferencesFromSnippetParameters)(this);
                }
                return undefined;
            }
            default:
                return [];
        }
    }
    static generateStepFromMablStep(mablCreateVariableStep, importer) {
        const humanizedName = mablCreateVariableStep.descriptor.name;
        const variableName = `user.${humanizedName}`;
        const generationType = mablCreateVariableStep.descriptor.generator.type;
        switch (generationType) {
            case CreateVariableStepDescriptor_1.VariableGenerator.ATTRIBUTE:
                const stepDescriptor = mablCreateVariableStep.toStepDescriptor();
                if (!('find' in stepDescriptor)) {
                    throw new Error('No FindDescriptor found for Create Variable Step');
                }
                if (!isAttributeGenerator(stepDescriptor.generator)) {
                    throw new Error('No attribute specified for mobile CreateVariableStep');
                }
                const find = { ...stepDescriptor.find };
                let findDescriptor;
                if ((0, mablscriptFind_1.isFindCustomDescriptor)(find) && find.foundElementSelectors) {
                    findDescriptor = {
                        type: find.findType,
                        foundElementSelectors: find.foundElementSelectors,
                        primarySelectors: find.findTarget,
                    };
                }
                else {
                    findDescriptor = {
                        selector: find.findTarget.selector,
                        type: find.findType,
                    };
                    if (find.findTarget.configuration) {
                        findDescriptor.configuration = find.findTarget.configuration;
                    }
                }
                const elementPropertyVariable = {
                    property: stepDescriptor.generator.attribute,
                    variableType: mablscriptFind_1.VariableType.ELEMENT_PROPERTY,
                    value: variable_constants_1.EMPTY_VARIABLE_VALUE_PLACEHOLDER,
                    name: variableName,
                    humanizedName,
                };
                return new CreateVariableStep(elementPropertyVariable, findDescriptor, find.findOptions);
            case CreateVariableStepDescriptor_1.VariableGenerator.ELEMENT_COUNT:
                if (mablCreateVariableStep.actions[0] instanceof FindAction_1.FindAction) {
                    const findDescriptor = mablCreateVariableStep.actions[0].toDescriptor();
                    let findOptions;
                    if ((0, mablscriptFind_1.isFindElementDescriptor)(findDescriptor)) {
                        findOptions = findDescriptor.findOptions;
                    }
                    const recordedVariable = {
                        property: 'count',
                        variableType: mablscriptFind_1.VariableType.ELEMENT_COUNT,
                        value: variable_constants_1.EMPTY_VARIABLE_VALUE_PLACEHOLDER,
                        name: variableName,
                        humanizedName,
                    };
                    return new CreateVariableStep(recordedVariable, {
                        type: findDescriptor?.findType,
                        foundElementSelectors: {
                            selector_type: 'element',
                        },
                        primarySelectors: findDescriptor.findTarget,
                    }, findOptions);
                }
                throw new Error('Unexpected first action for generating variable from element count');
            case CreateVariableStepDescriptor_1.VariableGenerator.EMAIL:
                const emailVariable = {
                    value: variable_constants_1.EMPTY_VARIABLE_VALUE_PLACEHOLDER,
                    variableType: mablscriptFind_1.VariableType.MABL_MAILBOX,
                    name: variableName,
                    humanizedName,
                    readOnly: false,
                };
                importer.variables[variableName] = emailVariable;
                return new CreateVariableStep(emailVariable);
            case CreateVariableStepDescriptor_1.VariableGenerator.JAVASCRIPT:
                let javascriptVal;
                if (isJavascriptGenerator(mablCreateVariableStep.descriptor.generator)) {
                    javascriptVal =
                        mablCreateVariableStep.descriptor.generator.javaScript;
                }
                else if ((0, EvaluateJSStep_1.isJavascriptAction)(mablCreateVariableStep.actions[0])) {
                    javascriptVal = mablCreateVariableStep.actions[0].javaScript;
                }
                if (javascriptVal) {
                    javascriptVal = (0, snippetUtils_1.canonicalizeJavaScriptDescriptor)(javascriptVal, importer.variables);
                    let jsVal;
                    let snippetVal;
                    if ((0, SnippetsDescriptor_1.isInlineSnippetDescriptor)(javascriptVal)) {
                        jsVal = {
                            inlineSnippet: javascriptVal.inlineSnippet,
                            parameterOverrides: javascriptVal.parameterOverrides,
                        };
                        snippetVal = javascriptVal.inlineSnippet;
                    }
                    else if ((0, SnippetsDescriptor_1.isReusableSnippetDescriptor)(javascriptVal)) {
                        jsVal = {
                            snippetId: javascriptVal.id ?? javascriptVal.snippetId,
                            snippetInvariantId: javascriptVal.invariant_id ?? javascriptVal.snippetInvariantId,
                            parameterOverrides: javascriptVal.parameterOverrides,
                        };
                        snippetVal = importer.snippets[javascriptVal.snippetInvariantId];
                    }
                    else if ((0, SnippetsDescriptor_1.isLegacyInlineJavaScriptDescriptor)(javascriptVal)) {
                        jsVal = {
                            encodedJS: javascriptVal.encodedJS,
                        };
                        snippetVal = {
                            body: javascriptVal.encodedJS,
                            snippet_type: 'javascript',
                        };
                    }
                    else if ((0, SnippetsDescriptor_1.isLegacyReusableSnippetDescriptor)(javascriptVal)) {
                        jsVal = {
                            snippetInvariantId: javascriptVal.snippetInvariantId,
                        };
                        snippetVal = importer.snippets[javascriptVal.snippetInvariantId];
                    }
                    const recordedVariable = {
                        value: variable_constants_1.EMPTY_VARIABLE_VALUE_PLACEHOLDER,
                        variableType: mablscriptFind_1.VariableType.JAVASCRIPT,
                        javaScript: jsVal,
                        snippet: snippetVal,
                        name: variableName,
                        humanizedName,
                    };
                    return new CreateVariableStep(recordedVariable);
                }
                throw new Error('Unexpected first action for generating variable from JavaScript');
            case CreateVariableStepDescriptor_1.VariableGenerator.PATTERN:
                const pattern = mablCreateVariableStep.descriptor.generator.pattern;
                const canonicalizedPattern = (0, variable_utils_1.canonicalizeVariablePattern)(importer.variables, pattern);
                const patternVariable = {
                    name: variableName,
                    variableType: mablscriptFind_1.VariableType.GENERATED,
                    pattern: canonicalizedPattern,
                    humanizedName,
                    value: (0, variable_utils_1.safelyGeneratePatternPreview)(canonicalizedPattern, importer.variables, undefined, true),
                };
                importer.variables[variableName] = patternVariable;
                return new CreateVariableStep(patternVariable);
            case CreateVariableStepDescriptor_1.VariableGenerator.COOKIE_ATTRIBUTE:
                const actions = mablCreateVariableStep.actions;
                if (actions.length !== 2) {
                    throw new Error('Unexpected number of actions for generating variable from cookie attribute');
                }
                if (!(actions[0] instanceof FindAction_1.FindAction &&
                    actions[0].findDescriptor.findType === mablscriptFind_1.FindType.FIND_COOKIE)) {
                    throw new Error('Unexpected first action for generating variable from cookie attribute');
                }
                if (!(actions[1] instanceof ExtractAction_1.ExtractAction)) {
                    throw new Error('Unexpected second action for generating variable from cookie attribute');
                }
                const findCookieDescriptor = actions[0].findDescriptor;
                const extractAction = actions[1];
                const cookieVariable = {
                    name: variableName,
                    variableType: mablscriptFind_1.VariableType.COOKIE,
                    value: variable_constants_1.EMPTY_VARIABLE_VALUE_PLACEHOLDER,
                    humanizedName,
                    readOnly: false,
                    property: extractAction.extractionAttribute,
                };
                importer.variables[variableName] = cookieVariable;
                const cookieFindDescriptor = {
                    type: 'cookie',
                    cookieSelector: findCookieDescriptor.findTarget,
                };
                return new CreateVariableStep(cookieVariable, cookieFindDescriptor);
            default:
                throw new Error(`Unsupported VariableGenerator type supplied: ${generationType}`);
        }
    }
    static create(descriptor) {
        const step = new CreateVariableStep(descriptor.variable, descriptor.findDescriptor, descriptor.findOptions);
        step.setStepId(descriptor.id ?? MablStepV2_1.MablStepV2.generateStepId());
        return step;
    }
}
exports.default = CreateVariableStep;
function createVariableStepWithUpdatedReusableSnippet(step, snippet) {
    if (step.variable.variableType !== mablscriptFind_1.VariableType.JAVASCRIPT ||
        !(0, snippetUtils_1.isSnippetReusableAndRelevant)(step.variable.javaScript, snippet)) {
        return step;
    }
    const updatedVariable = { ...step.variable };
    updatedVariable.javaScript = (0, snippetUtils_1.updateJavaScriptDescriptorIfReusable)(step.variable.javaScript, snippet);
    updatedVariable.snippet = snippet;
    return new CreateVariableStep(updatedVariable);
}
function isAttributeGenerator(generator) {
    return generator?.type === 'ATTRIBUTE' && !!generator?.attribute;
}
function isJavascriptGenerator(generator) {
    return (generator?.type === CreateVariableStepDescriptor_1.VariableGenerator.JAVASCRIPT && !!generator?.javaScript);
}
function isCreateVariableStepInstance(step) {
    return step.getStepType?.() === mablscript_step_types_1.StepType.CREATE_VARIABLE;
}
function humanizeCreateVariableStep(step) {
    let predicate;
    switch (step.variable.variableType) {
        case mablscriptFind_1.VariableType.GENERATED:
            predicate = `Generate a string with format "${(0, dom_util_1.compactWhitespace)(step.variable.pattern)}"`;
            break;
        case mablscriptFind_1.VariableType.ELEMENT_PROPERTY:
            predicate = `Extract "${step.variable.property}" from ${(0, StepWithFind_1.humanizeFind)(step)}`;
            break;
        case mablscriptFind_1.VariableType.JAVASCRIPT:
            predicate = `Evaluate ${(0, mablscriptFind_1.humanizeSnippet)(getSnippetInvariantId(step), step.variable.snippet)}`;
            break;
        case mablscriptFind_1.VariableType.MABL_MAILBOX:
            predicate = `Generate a new mabl mailbox email address`;
            break;
        case mablscriptFind_1.VariableType.ELEMENT_COUNT:
            predicate = `Count ${(0, StepWithFind_1.humanizeFind)(step)}`;
            break;
        case mablscriptFind_1.VariableType.COOKIE:
            predicate =
                step.variable.property === 'value'
                    ? `Extract value of ${(0, StepWithFind_1.humanizeFind)(step)}`
                    : `Extract cookie property "${step.variable.property}" from ${(0, StepWithFind_1.humanizeFind)(step)}`;
            break;
    }
    if (predicate) {
        const varDisplay = step.variable.humanizedName || step.variable.name;
        return `${predicate} and assign it to variable "${varDisplay}"`;
    }
    throw new Error('Invalid step; humanized description cannot be generated.');
}
function getSnippetInvariantId(step) {
    if (step.variable.variableType === mablscriptFind_1.VariableType.JAVASCRIPT) {
        const { javaScript } = step.variable;
        if ((0, SnippetsDescriptor_1.isReusableSnippetDescriptor)(javaScript) ||
            (0, SnippetsDescriptor_1.isLegacyReusableSnippetDescriptor)(javaScript)) {
            return javaScript.snippetInvariantId;
        }
    }
    return;
}
function createVariableStepToAIString(step) {
    const result = {
        stepType: step.stepType,
        variable_name: step.variable.humanizedName || step.variable.name,
        source_type: step.variable.variableType,
    };
    switch (step.variable.variableType) {
        case mablscriptFind_1.VariableType.GENERATED:
            result.pattern = step.variable.pattern;
            break;
        case mablscriptFind_1.VariableType.ELEMENT_PROPERTY:
            result.property = step.variable.property;
            if (step.findDescriptor) {
                result.target = (0, StepWithFind_1.findDescriptorToAIObject)(step.findDescriptor, step.findOptions);
            }
            break;
        case mablscriptFind_1.VariableType.JAVASCRIPT:
            if (step.variable.snippet?.name) {
                result.snippet_name = step.variable.snippet.name;
            }
            break;
        case mablscriptFind_1.VariableType.MABL_MAILBOX:
            break;
        case mablscriptFind_1.VariableType.ELEMENT_COUNT:
            if (step.findDescriptor) {
                result.target = (0, StepWithFind_1.findDescriptorToAIObject)(step.findDescriptor, step.findOptions);
            }
            break;
        case mablscriptFind_1.VariableType.COOKIE:
            result.property = step.variable.property;
            if (step.findDescriptor) {
                result.target = (0, StepWithFind_1.findDescriptorToAIObject)(step.findDescriptor, step.findOptions);
            }
            break;
    }
    return (0, yaml_utils_1.toYaml)(result);
}
