"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.refactorNameInCode = refactorNameInCode;
exports.refactorNameInString = refactorNameInString;
exports.refactorNameInValue = refactorNameInValue;
exports.createFakeDataTree = createFakeDataTree;
exports.refactorNameInStep = refactorNameInStep;
const lodash_1 = require("lodash");
const index_js_1 = require("../bindings/index.js");
const language_js_1 = require("../types/plugin/language.js");
const splitStringWithBindings = (value) => {
    const stringSegments = (0, index_js_1.getDynamicStringSegments)(value.trim());
    return stringSegments.map((segment) => {
        const length = segment.length;
        if ((0, index_js_1.isExactBinding)(segment)) {
            return { dynamic: true, value: segment.substring(2, length - 2) };
        }
        return { dynamic: false, value: segment };
    });
};
async function refactorNameInCode({ value, oldName, newName, dataTree, extractPairs, suffixes, namespace }) {
    let pairs;
    if (namespace) {
        const namespacedEntitiesToExtract = {
            [namespace]: new Set([oldName])
        };
        pairs = await extractPairs(value, new Set(), dataTree, namespacedEntitiesToExtract);
    }
    else {
        pairs = await extractPairs(value, new Set([oldName]), dataTree);
    }
    let position = 0;
    let result = '';
    for (const { binding, range } of pairs) {
        if (suffixes) {
            // only refactor if the code after the binding matches a suffix
            const restOfCode = value.slice(range.start + binding.length);
            if (!suffixes.some((suffix) => restOfCode.startsWith(suffix))) {
                result += value.slice(position, range.end + 1);
                position = range.end + 1;
                continue;
            }
        }
        result += value.slice(position, range.start) + newName;
        position = range.start + binding.length;
    }
    return result + value.slice(position);
}
async function refactorNameInSegment({ segment, oldName, newName, dataTree, extractPairs, namespace }) {
    if (segment.dynamic) {
        const value = await refactorNameInCode({
            value: segment.value,
            oldName,
            newName,
            dataTree,
            extractPairs,
            namespace
        });
        if (value === null) {
            return null;
        }
        return { dynamic: true, value };
    }
    return segment;
}
async function refactorNameInString({ value, oldName, newName, dataTree, extractPairs, namespace }) {
    const segments = splitStringWithBindings(value);
    const newSegments = await Promise.all(segments.map((segment) => refactorNameInSegment({ segment, oldName, newName, dataTree, extractPairs, namespace })));
    if (newSegments.filter((segment) => segment === null).length) {
        return value;
    }
    return (0, index_js_1.joinStringWithBindings)(newSegments.filter((segment) => segment !== null));
}
async function refactorNameInValue({ oldValue, oldName, newName, dataTree, extractPairs, namespace, includeNestedObjects }) {
    if ((0, lodash_1.isArray)(oldValue)) {
        return Promise.all(oldValue.map(async (value) => {
            if (typeof value === 'string') {
                return refactorNameInString({
                    value,
                    oldName,
                    newName,
                    dataTree,
                    extractPairs,
                    namespace
                });
            }
            else if (includeNestedObjects && value !== null && typeof value === 'object') {
                return refactorNameInValue({
                    oldValue: value,
                    oldName,
                    newName,
                    dataTree,
                    extractPairs,
                    namespace,
                    includeNestedObjects: true
                });
            }
            else {
                return value;
            }
        }));
    }
    else if ((0, lodash_1.isString)(oldValue)) {
        return refactorNameInString({
            value: oldValue,
            oldName,
            newName,
            dataTree,
            extractPairs,
            namespace
        });
    }
    else if ((0, lodash_1.isObject)(oldValue)) {
        const entries = await Promise.all(Object.entries(oldValue).map(async ([key, value]) => {
            const newValue = await refactorNameInValue({
                oldValue: value,
                oldName,
                newName,
                dataTree,
                extractPairs,
                namespace,
                includeNestedObjects
            });
            return [key, newValue];
        }));
        return Object.fromEntries(entries);
    }
    return oldValue;
}
function createFakeDataTree(dsls) {
    const fakeDataTree = {};
    for (const dsl of dsls) {
        Object.values(dsl).forEach((entity) => {
            const name = entity.name || entity.widgetName;
            if (!name) {
                return;
            }
            fakeDataTree[name] = {};
        });
    }
    return fakeDataTree;
}
async function refactorNameInStep({ oldName, newName, dataTree, suffixes, namespace, configuration, pluginId, extractor }) {
    for (const [key, value] of Object.entries(configuration)) {
        if ((0, lodash_1.isString)(value)) {
            let newValue = null;
            // Code body's vs plain text bodies (JS, Python vs HTTP, etc)
            if (key === 'body' && (pluginId === language_js_1.LanguagePluginID.JavaScript || pluginId === language_js_1.LanguagePluginID.Python)) {
                newValue = await refactorNameInCode({
                    value,
                    oldName,
                    newName,
                    dataTree,
                    extractPairs: extractor,
                    suffixes,
                    namespace
                });
            }
            else {
                newValue = await refactorNameInString({
                    value,
                    oldName,
                    newName,
                    dataTree,
                    extractPairs: extractor,
                    namespace
                });
            }
            if (!(0, lodash_1.isEqual)(newValue, value)) {
                configuration[key] = newValue;
            }
        }
        else if (typeof value === 'object' && value !== null) {
            configuration[key] = await refactorNameInValue({
                oldValue: value,
                oldName,
                newName,
                dataTree,
                extractPairs: extractor,
                namespace,
                includeNestedObjects: true
            });
        }
    }
}
//# sourceMappingURL=refactor.js.map