"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.humanizeAssertVariableStep = humanizeAssertVariableStep;
exports.assertVariableStepToAIString = assertVariableStepToAIString;
const dom_util_1 = require("@mablhq-internal/mablscript-find/dom-util");
const mablscriptFind_1 = require("@mablhq/test-model/mablscriptFind");
const variable_names_util_1 = require("../../variable-names-util");
const assertionUtil_1 = require("../assertionUtil");
const common_1 = require("../../common");
const BaseStep_1 = __importDefault(require("./BaseStep"));
const type_utils_1 = require("../../type-utils");
const MablAction_1 = require("@mablhq/test-model/MablAction");
const AssertStep_1 = require("@mablhq/test-model/steps/AssertStep");
const mablscript_step_types_1 = require("../../mablscript-step-types");
const assert_utils_1 = require("./assert-utils");
const ConditionDescriptor_1 = require("@mablhq/test-model/types/ConditionDescriptor");
const yaml_utils_1 = require("../yaml-utils");
const CONDITIONAL_TYPE_ELSEIF = 'ELSEIF';
class AssertVariableStep extends BaseStep_1.default {
    static getStepType() {
        return mablscript_step_types_1.StepType.ASSERT_VARIABLE;
    }
    constructor(assertionArguments) {
        const { assertionType, onFailure, expectedValue, selectionType, variable, wrapInConditional, wrapInConditionalType, caseInsensitive, } = assertionArguments;
        super(AssertVariableStep.getStepType());
        this.options = {
            editable: true,
            executionContext: 'background',
        };
        this.assertionType = assertionType;
        this.caseInsensitive = caseInsensitive;
        this.onFailure = onFailure;
        this.expectedValue = (0, assertionUtil_1.parseAssertionExpectedValue)(expectedValue);
        this.selectionType = selectionType;
        this.variable = variable;
        this.wrapInConditional = wrapInConditional;
        this.wrapInConditionalType = wrapInConditionalType;
    }
    generateMablscript() {
        const extractVariable = `get_variable_value(${this.variable?.name})`;
        const assertionArguments = this.generateAssertionArguments();
        const assertionOptions = this.generateAssertionOptionsArgument();
        const conditionOptions = this.generateConditionOptionsArgument();
        const assertionTypeMablscript = (0, assertionUtil_1.getAssertionMablscriptText)(this.assertionType);
        const assertionAction = `${extractVariable}.evaluate_condition("${assertionTypeMablscript}"${assertionArguments}${conditionOptions})`;
        if (this.wrapInConditional) {
            return this.wrapInConditionalType === CONDITIONAL_TYPE_ELSEIF
                ? `conditional_else().${assertionAction}.conditional_else_if()`
                : `${assertionAction}.conditional_if()`;
        }
        return `${assertionAction}.assert(${assertionOptions})`;
    }
    generateAssertionArguments() {
        return `, "${(0, mablscriptFind_1.escapeMablscriptString)((0, dom_util_1.normalizeText)(this.expectedValue))}"`;
    }
    generateAssertionOptionsArgument() {
        return this.onFailure !== undefined &&
            this.onFailure !== AssertStep_1.OnFailure.FailImmediately
            ? `{onFailure: "${this.onFailure}"}`
            : '';
    }
    generateConditionOptionsArgument() {
        if (!this.caseInsensitive) {
            return '';
        }
        return `, ${(0, MablAction_1.convertObjectToMablscriptArgs)({
            caseInsensitive: this.caseInsensitive,
        })}`;
    }
    inputVariables() {
        return (0, type_utils_1.distinct)([
            this.variable?.name,
            ...(0, variable_names_util_1.extractVariableNamesFromPattern)(this.expectedValue),
        ]);
    }
    setOnFailure(onFailure) {
        if (this.onFailure === onFailure) {
            return false;
        }
        this.onFailure = onFailure;
        return true;
    }
    static generateStepFromMablStep(mablAssertStep, suppliedVariable) {
        let wrapInConditionalType;
        if ((0, assert_utils_1.isIfConditionStep)(mablAssertStep)) {
            wrapInConditionalType = mablscript_step_types_1.ConditionalType.IF;
        }
        else if ((0, assert_utils_1.isElseIfConditionStep)(mablAssertStep)) {
            wrapInConditionalType = mablscript_step_types_1.ConditionalType.ELSEIF;
        }
        const finalStepArg = {
            selectionType: 'variable',
            assertionType: mablAssertStep.assertionType ??
                (0, assert_utils_1.getOptionalComparisonType)(mablAssertStep.conditionAction.conditionDescriptor),
            caseInsensitive: (0, ConditionDescriptor_1.getOptionalConditionOptions)(mablAssertStep.conditionAction.conditionDescriptor)?.caseInsensitive,
            onFailure: mablAssertStep.onFailure,
            expectedValue: mablAssertStep.assertionValue ??
                (0, ConditionDescriptor_1.getOptionalComparatorValue)(mablAssertStep.conditionAction.conditionDescriptor),
            wrapInConditionalType,
        };
        if (wrapInConditionalType) {
            finalStepArg.wrapInConditional = true;
        }
        if (suppliedVariable && !!Object.keys(suppliedVariable).length) {
            finalStepArg.variable = suppliedVariable;
        }
        return new AssertVariableStep(finalStepArg);
    }
    static create(descriptor) {
        const step = new AssertVariableStep(descriptor);
        step.generateStepId();
        return step;
    }
}
exports.default = AssertVariableStep;
function humanizeAssertVariableStep(step) {
    const prependedText = !step.wrapInConditional
        ? 'Assert'
        : step.wrapInConditionalType === CONDITIONAL_TYPE_ELSEIF
            ? 'ELSE IF'
            : 'IF';
    const assertionText = (0, mablscriptFind_1.humanizeText)(step.expectedValue);
    const assertionTypeHumanized = (0, common_1.getAssertionHumanizedText)(step.assertionType);
    const varDisplay = step.variable?.humanizedName || step.variable?.name;
    return `${prependedText} value of variable "${varDisplay}" ${assertionTypeHumanized} ${assertionText}`;
}
function assertVariableStepToAIString(step) {
    const result = {};
    if (step.wrapInConditional) {
        result.stepType =
            step.wrapInConditionalType === CONDITIONAL_TYPE_ELSEIF ? 'else_if' : 'if';
        result.condition = {
            variable: step.variable?.humanizedName || step.variable?.name,
            assertion_type: step.assertionType,
            expected_value: step.expectedValue,
            case_insensitive: step.caseInsensitive || undefined,
        };
    }
    else {
        result.stepType = step.stepType;
        result.variable = step.variable?.humanizedName || step.variable?.name;
        result.assertion_type = step.assertionType;
        result.expected_value = step.expectedValue;
        if (step.caseInsensitive) {
            result.case_insensitive = true;
        }
        if (step.onFailure && step.onFailure !== AssertStep_1.OnFailure.FailImmediately) {
            result.on_failure = step.onFailure;
        }
    }
    return (0, yaml_utils_1.toYaml)(result);
}
