"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isSnippetStep = isSnippetStep;
exports.getResolvedSnippetParameters = getResolvedSnippetParameters;
exports.calculateRunExecutionHash = calculateRunExecutionHash;
exports.getVariableReferencesFromSnippetParameters = getVariableReferencesFromSnippetParameters;
exports.isSnippetReusableAndRelevant = isSnippetReusableAndRelevant;
exports.canonicalizeJavaScriptDescriptor = canonicalizeJavaScriptDescriptor;
exports.updateJavaScriptDescriptorIfReusable = updateJavaScriptDescriptorIfReusable;
const mablscriptFind_1 = require("@mablhq/test-model/mablscriptFind");
const SnippetsDescriptor_1 = require("@mablhq/test-model/types/SnippetsDescriptor");
const object_hash_1 = __importDefault(require("object-hash"));
const mablscript_step_types_1 = require("../mablscript-step-types");
const type_utils_1 = require("../type-utils");
const variable_utils_1 = require("../variable-utils");
const variable_names_util_1 = require("../variable-names-util");
function isSnippetStep(step) {
    return !!(((0, mablscript_step_types_1.isCreateVariableStep)(step) &&
        step.variable.variableType === mablscriptFind_1.VariableType.JAVASCRIPT) ||
        (0, mablscript_step_types_1.isEvaluateJSStep)(step));
}
function getResolvedSnippetParameters(step, variables) {
    const snippetParameters = getStepSnippetParametersForStep(step);
    const parameterOverrides = getStepSnippetParameterOverridesForStep(step);
    return resolveSnippetParameterValues(snippetParameters, parameterOverrides, variables);
}
function calculateRunExecutionHash(encodedJS, parameters, parameterOverrides, variables) {
    const effectiveParameters = resolveSnippetParameterValues(parameters ?? [], parameterOverrides ?? [], variables);
    const hashTarget = {
        encodedJS,
        effectiveParameters,
    };
    return (0, object_hash_1.default)(hashTarget, {
        algorithm: 'sha1',
    });
}
function resolveSnippetParameterValues(snippetParameters, parameterOverrides, variables) {
    if (!snippetParameters) {
        return;
    }
    return snippetParameters.reduce((parameterValues, snippetParameter) => {
        const { id, name, default_value: defaultValue } = snippetParameter;
        const overrideValue = parameterOverrides?.find((parameterOverrides) => parameterOverrides.id === id)?.value;
        const value = overrideValue ?? defaultValue;
        const resolvedValue = value === undefined
            ? value
            : generatePatternIfVariablesExist(value, variables);
        parameterValues[name] = resolvedValue;
        return parameterValues;
    }, {});
}
function generatePatternIfVariablesExist(pattern, variables) {
    if (!variables) {
        return pattern;
    }
    return (0, variable_utils_1.safelyGeneratePatternPreview)(pattern, variables);
}
function getStepSnippetParametersForStep(step) {
    if ((0, mablscript_step_types_1.isCreateVariableStep)(step) &&
        step.variable.variableType === mablscriptFind_1.VariableType.JAVASCRIPT) {
        return step.variable?.snippet?.parameters;
    }
    if ((0, mablscript_step_types_1.isEvaluateJSStep)(step)) {
        return step.snippet?.parameters;
    }
    return;
}
function getStepSnippetParameterOverridesForStep(step) {
    if ((0, mablscript_step_types_1.isCreateVariableStep)(step) &&
        step.variable.variableType === mablscriptFind_1.VariableType.JAVASCRIPT &&
        ((0, SnippetsDescriptor_1.isInlineSnippetDescriptor)(step.variable.javaScript) ||
            (0, SnippetsDescriptor_1.isReusableSnippetDescriptor)(step.variable.javaScript))) {
        return step.variable?.javaScript?.parameterOverrides;
    }
    if ((0, mablscript_step_types_1.isEvaluateJSStep)(step) &&
        ((0, SnippetsDescriptor_1.isInlineSnippetDescriptor)(step.javaScript) ||
            (0, SnippetsDescriptor_1.isReusableSnippetDescriptor)(step.javaScript))) {
        return step.javaScript.parameterOverrides;
    }
    return;
}
function getVariableReferencesFromSnippetParameters(step, variables) {
    const snippetParameters = getStepSnippetParametersForStep(step);
    const parameterOverrides = getStepSnippetParameterOverridesForStep(step);
    const finalSnippetParameters = resolveSnippetParameterValues(snippetParameters, parameterOverrides);
    if (!finalSnippetParameters) {
        return [];
    }
    const variableReferences = [];
    Object.values(finalSnippetParameters).forEach((parameterValue) => {
        if (parameterValue) {
            const canonicalizedValue = variables
                ? (0, variable_utils_1.canonicalizeVariablePattern)(variables, parameterValue) ??
                    parameterValue
                : parameterValue;
            const extractedVariableReferences = (0, variable_names_util_1.extractVariableNamesFromPattern)(canonicalizedValue);
            variableReferences.push(...extractedVariableReferences);
        }
    });
    return (0, type_utils_1.distinct)(variableReferences);
}
function isSnippetReusableAndRelevant(javaScript, snippet) {
    if ((0, SnippetsDescriptor_1.isInlineSnippetDescriptor)(javaScript) ||
        (0, SnippetsDescriptor_1.isLegacyInlineJavaScriptDescriptor)(javaScript)) {
        return false;
    }
    if (!snippet?.reusable ||
        !snippet.id ||
        !snippet.invariant_id ||
        javaScript.snippetInvariantId !== snippet.invariant_id) {
        return false;
    }
    return true;
}
function canonicalizeJavaScriptDescriptor(javaScript, variables) {
    if (!(0, SnippetsDescriptor_1.isInlineSnippetDescriptor)(javaScript) &&
        !(0, SnippetsDescriptor_1.isReusableSnippetDescriptor)(javaScript)) {
        return javaScript;
    }
    const parameterOverrides = javaScript.parameterOverrides;
    if (!parameterOverrides || parameterOverrides.length === 0) {
        return javaScript;
    }
    const canonicalizedOverrides = parameterOverrides.map((override) => {
        if (override.value === undefined) {
            return override;
        }
        const canonicalizedValue = (0, variable_utils_1.canonicalizeVariablePattern)(variables, override.value);
        return {
            ...override,
            value: canonicalizedValue ?? override.value,
        };
    });
    if ((0, SnippetsDescriptor_1.isInlineSnippetDescriptor)(javaScript)) {
        return {
            ...javaScript,
            parameterOverrides: canonicalizedOverrides,
        };
    }
    return {
        ...javaScript,
        parameterOverrides: canonicalizedOverrides,
    };
}
function updateJavaScriptDescriptorIfReusable(javaScript, snippet) {
    if (!isSnippetReusableAndRelevant(javaScript, snippet) ||
        !snippet.id ||
        !snippet.invariant_id) {
        return javaScript;
    }
    if ((0, SnippetsDescriptor_1.isLegacyReusableSnippetDescriptor)(javaScript) && snippet.parameters) {
        return {
            snippetId: snippet.id,
            snippetInvariantId: snippet.invariant_id,
            parameterOverrides: [],
        };
    }
    else if ((0, SnippetsDescriptor_1.isReusableSnippetDescriptor)(javaScript)) {
        return {
            snippetId: snippet.id,
            snippetInvariantId: snippet.invariant_id,
            parameterOverrides: javaScript.parameterOverrides,
        };
    }
    return javaScript;
}
