import { parser as pythonParser } from "@lezer/python";
import { flattenBlocks } from "@superblocksteam/library-shared";
import { BlockType, extractJsEvaluationPairsWithTokenizer, extractPythonEvaluationPairsWithParser, getPluginType, isControlBlock, isStepBlock, LanguagePluginID, refactorNameInStep, refactorNameInString, } from "@superblocksteam/shared";
import { tokenize } from "esprima";
import { isEqual } from "lodash-es";
const extractPythonEvaluationPairs = async (code, entities, dataTree, namespacedEntitiesToExtract) => {
    return extractPythonEvaluationPairsWithParser(code, entities, dataTree, pythonParser, namespacedEntitiesToExtract);
};
export const extractJsEvaluationPairs = async (jsSnippet, entitiesToExtract, dataTree, namespacedEntitiesToExtract) => {
    return extractJsEvaluationPairsWithTokenizer(jsSnippet, entitiesToExtract, dataTree, tokenize, namespacedEntitiesToExtract);
};
function getExtractorByPluginId(pluginId) {
    if (!pluginId) {
        return extractJsEvaluationPairs;
    }
    switch (pluginId.trim().toLowerCase()) {
        case LanguagePluginID.Python:
            return extractPythonEvaluationPairs;
        case LanguagePluginID.JavaScript:
        default:
            return extractJsEvaluationPairs;
    }
}
export async function refactorNameInBlocks(params) {
    const { blocks, oldName, newName, namespace } = params;
    const flattenedBlocks = flattenBlocks(blocks);
    for (const block of flattenedBlocks) {
        const pluginType = getPluginType(block) ?? undefined;
        const extractor = getExtractorByPluginId(pluginType);
        if (isStepBlock(block) && pluginType) {
            const configuration = block.config[pluginType];
            if (typeof configuration !== "object" || configuration == null) {
                continue;
            }
            await refactorNameInStep({
                ...params,
                dataTree: {
                    [newName]: {},
                    [oldName]: {},
                },
                pluginId: pluginType,
                configuration: configuration,
                extractor,
            });
        }
        else if (isControlBlock(block)) {
            for (const [value, setValue] of getSetControlBlockExpressions(block)) {
                const newValue = await refactorNameInString({
                    value,
                    oldName,
                    newName,
                    dataTree: {
                        [newName]: {},
                        [oldName]: {},
                    },
                    namespace,
                    extractPairs: extractJsEvaluationPairs,
                });
                if (!isEqual(newValue, value)) {
                    setValue(newValue);
                }
            }
        }
    }
}
const makeGetSet = (val, propertyKey) => {
    return [
        val[propertyKey],
        (newVal) => {
            val[propertyKey] = newVal;
        },
    ];
};
function getSetControlBlockExpressions(block) {
    const { config, type } = block;
    const results = [];
    switch (type) {
        case BlockType.BREAK: {
            const controlConfig = config;
            results.push(makeGetSet(controlConfig, "condition"));
            break;
        }
        case BlockType.THROW: {
            const controlConfig = config;
            results.push(makeGetSet(controlConfig, "error"));
            break;
        }
        case BlockType.RETURN: {
            const controlConfig = config;
            results.push(makeGetSet(controlConfig, "data"));
            break;
        }
        case BlockType.WAIT: {
            const controlConfig = config;
            results.push(makeGetSet(controlConfig, "condition"));
            break;
        }
        case BlockType.PARALLEL: {
            const controlConfig = config;
            if (controlConfig.dynamic) {
                results.push(makeGetSet(controlConfig.dynamic, "paths"));
            }
            break;
        }
        case BlockType.CONDITION: {
            const controlConfig = config;
            if (controlConfig.if) {
                results.push(makeGetSet(controlConfig.if, "condition"));
            }
            for (const cond of controlConfig.elseIf ?? []) {
                results.push(makeGetSet(cond, "condition"));
            }
            break;
        }
        case BlockType.LOOP: {
            const controlConfig = config;
            results.push(makeGetSet(controlConfig, "range"));
            break;
        }
        case BlockType.TRY_CATCH: {
            break;
        }
        case BlockType.VARIABLES: {
            const controlConfig = config;
            for (const variable of controlConfig.items) {
                if (variable.value) {
                    results.push(makeGetSet(variable, "value"));
                }
            }
            break;
        }
        case BlockType.SEND: {
            const controlConfig = config;
            results.push(makeGetSet(controlConfig, "message"));
            break;
        }
        case BlockType.STREAM: {
            break;
        }
        default: {
            const exhaustiveCheck = type;
            throw new Error(`Unhandled type: ${exhaustiveCheck}`);
        }
    }
    return results;
}
//# sourceMappingURL=blocks.js.map