"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setParseGradleFunc = setParseGradleFunc;
exports.handleAssignment = handleAssignment;
exports.handleDepString = handleDepString;
exports.handleKotlinShortNotationDep = handleKotlinShortNotationDep;
exports.handleLongFormDep = handleLongFormDep;
exports.handlePlugin = handlePlugin;
exports.handlePredefinedRegistryUrl = handlePredefinedRegistryUrl;
exports.handleCustomRegistryUrl = handleCustomRegistryUrl;
exports.handleLibraryDep = handleLibraryDep;
exports.handleApplyFrom = handleApplyFrom;
exports.handleImplicitGradlePlugin = handleImplicitGradlePlugin;
const tslib_1 = require("tslib");
const node_url_1 = tslib_1.__importDefault(require("node:url"));
const upath_1 = tslib_1.__importDefault(require("upath"));
const logger_1 = require("../../../../logger");
const fs_1 = require("../../../../util/fs");
const regex_1 = require("../../../../util/regex");
const utils_1 = require("../utils");
const common_1 = require("./common");
// needed to break circular dependency
let parseGradle;
function setParseGradleFunc(func) {
    parseGradle = func;
}
function handleAssignment(ctx) {
    const key = (0, common_1.loadFromTokenMap)(ctx, 'keyToken')[0].value;
    const valTokens = (0, common_1.loadFromTokenMap)(ctx, 'valToken');
    if (valTokens.length > 1) {
        // = template string with multiple variables
        ctx.tokenMap.templateStringTokens = valTokens;
        handleDepString(ctx);
        delete ctx.tokenMap.templateStringTokens;
    }
    else if (valTokens[0].type === 'symbol') {
        // foo = bar || foo = "${bar}"
        const varData = (0, common_1.findVariable)(valTokens[0].value, ctx);
        if (varData) {
            ctx.globalVars[key] = { ...varData };
        }
    }
    else {
        // = string value
        const dep = (0, utils_1.parseDependencyString)(valTokens[0].value);
        if (dep) {
            dep.groupName = key;
            dep.managerData = {
                fileReplacePosition: valTokens[0].offset + dep.depName.length + 1,
                packageFile: ctx.packageFile,
            };
            ctx.deps.push(dep);
        }
        ctx.globalVars[key] = {
            key,
            value: valTokens[0].value,
            fileReplacePosition: valTokens[0].offset,
            packageFile: ctx.packageFile,
        };
    }
    return ctx;
}
function handleDepString(ctx) {
    const stringTokens = (0, common_1.loadFromTokenMap)(ctx, 'templateStringTokens');
    const templateString = (0, common_1.interpolateString)(stringTokens, ctx);
    if (!templateString) {
        return ctx;
    }
    const dep = (0, utils_1.parseDependencyString)(templateString);
    if (!dep) {
        return ctx;
    }
    let packageFile;
    let fileReplacePosition;
    for (const token of stringTokens) {
        if (token.type === 'symbol') {
            const varData = (0, common_1.findVariable)(token.value, ctx);
            if (varData) {
                packageFile = varData.packageFile;
                fileReplacePosition = varData.fileReplacePosition;
                if (varData.value === dep.currentValue) {
                    dep.managerData = { fileReplacePosition, packageFile };
                    dep.groupName = varData.key;
                }
            }
        }
    }
    if (!dep.managerData) {
        const lastToken = stringTokens[stringTokens.length - 1];
        if (lastToken?.type === 'string-value' &&
            dep.currentValue &&
            lastToken.value.includes(dep.currentValue)) {
            packageFile = ctx.packageFile;
            if (stringTokens.length === 1) {
                fileReplacePosition = lastToken.offset + dep.depName.length + 1;
            }
            else {
                fileReplacePosition =
                    lastToken.offset + lastToken.value.lastIndexOf(dep.currentValue);
            }
            delete dep.groupName;
        }
        else {
            dep.skipReason = 'contains-variable';
        }
        dep.managerData = { fileReplacePosition, packageFile };
    }
    ctx.deps.push(dep);
    return ctx;
}
function handleKotlinShortNotationDep(ctx) {
    const moduleNameTokens = (0, common_1.loadFromTokenMap)(ctx, 'artifactId');
    const versionTokens = (0, common_1.loadFromTokenMap)(ctx, 'version');
    const moduleName = (0, common_1.interpolateString)(moduleNameTokens, ctx);
    const versionValue = (0, common_1.interpolateString)(versionTokens, ctx);
    if (!moduleName || !versionValue) {
        return ctx;
    }
    const groupIdArtifactId = `org.jetbrains.kotlin:kotlin-${moduleName}`;
    const dep = (0, utils_1.parseDependencyString)(`${groupIdArtifactId}:${versionValue}`);
    if (!dep) {
        return ctx;
    }
    dep.depName = moduleName;
    dep.packageName = groupIdArtifactId;
    dep.managerData = {
        fileReplacePosition: versionTokens[0].offset,
        packageFile: ctx.packageFile,
    };
    if (versionTokens.length > 1) {
        // = template string with multiple variables
        dep.skipReason = 'unspecified-version';
    }
    else if (versionTokens[0].type === 'symbol') {
        const varData = (0, common_1.findVariable)(versionTokens[0].value, ctx);
        if (varData) {
            dep.groupName = varData.key;
            dep.currentValue = varData.value;
            dep.managerData = {
                fileReplacePosition: varData.fileReplacePosition,
                packageFile: varData.packageFile,
            };
        }
    }
    ctx.deps.push(dep);
    return ctx;
}
function handleLongFormDep(ctx) {
    const groupIdTokens = (0, common_1.loadFromTokenMap)(ctx, 'groupId');
    const artifactIdTokens = (0, common_1.loadFromTokenMap)(ctx, 'artifactId');
    const versionTokens = (0, common_1.loadFromTokenMap)(ctx, 'version');
    const groupId = (0, common_1.interpolateString)(groupIdTokens, ctx);
    const artifactId = (0, common_1.interpolateString)(artifactIdTokens, ctx);
    const version = (0, common_1.interpolateString)(versionTokens, ctx);
    if (!groupId || !artifactId || !version) {
        return ctx;
    }
    const dep = (0, utils_1.parseDependencyString)([groupId, artifactId, version].join(':'));
    if (!dep) {
        return ctx;
    }
    const methodName = ctx.tokenMap.methodName ?? null;
    if (versionTokens.length > 1) {
        // = template string with multiple variables
        dep.skipReason = 'unspecified-version';
    }
    else if (versionTokens[0].type === 'symbol') {
        const varData = (0, common_1.findVariable)(versionTokens[0].value, ctx);
        if (varData) {
            dep.groupName = varData.key;
            dep.managerData = {
                fileReplacePosition: varData.fileReplacePosition,
                packageFile: varData.packageFile,
            };
        }
    }
    else {
        // = string value
        if (methodName?.[0]?.value === 'dependencySet') {
            dep.groupName = `${groupId}:${version}`;
        }
        dep.managerData = {
            fileReplacePosition: versionTokens[0].offset,
            packageFile: ctx.packageFile,
        };
    }
    ctx.deps.push(dep);
    return ctx;
}
function handlePlugin(ctx) {
    const methodName = (0, common_1.loadFromTokenMap)(ctx, 'methodName')[0];
    const pluginName = (0, common_1.loadFromTokenMap)(ctx, 'pluginName')[0];
    const pluginVersion = (0, common_1.loadFromTokenMap)(ctx, 'version');
    const plugin = pluginName.value;
    const depName = methodName.value === 'kotlin' ? `org.jetbrains.kotlin.${plugin}` : plugin;
    const packageName = `${depName}:${depName}.gradle.plugin`;
    const dep = {
        depType: 'plugin',
        depName,
        packageName,
        commitMessageTopic: `plugin ${depName}`,
        currentValue: pluginVersion[0].value,
        managerData: {
            fileReplacePosition: pluginVersion[0].offset,
            packageFile: ctx.packageFile,
        },
    };
    if (pluginVersion.length > 1) {
        // = template string with multiple variables
        dep.skipReason = 'unspecified-version';
    }
    else if (pluginVersion[0].type === 'symbol') {
        const varData = (0, common_1.findVariable)(pluginVersion[0].value, ctx);
        if (varData) {
            dep.groupName = varData.key;
            dep.currentValue = varData.value;
            dep.managerData = {
                fileReplacePosition: varData.fileReplacePosition,
                packageFile: varData.packageFile,
            };
        }
        else {
            dep.skipReason = 'unspecified-version';
        }
    }
    ctx.deps.push(dep);
    return ctx;
}
function isPluginRegistry(ctx) {
    if (ctx.tokenMap.registryScope) {
        const registryScope = (0, common_1.loadFromTokenMap)(ctx, 'registryScope')[0].value;
        return registryScope === 'pluginManagement';
    }
    return false;
}
function handlePredefinedRegistryUrl(ctx) {
    const registryName = (0, common_1.loadFromTokenMap)(ctx, 'registryUrl')[0].value;
    ctx.registryUrls.push({
        registryUrl: common_1.REGISTRY_URLS[registryName],
        scope: isPluginRegistry(ctx) ? 'plugin' : 'dep',
    });
    return ctx;
}
function handleCustomRegistryUrl(ctx) {
    let localVariables = ctx.globalVars;
    if (ctx.tokenMap.name) {
        const nameTokens = (0, common_1.loadFromTokenMap)(ctx, 'name');
        const nameValue = (0, common_1.interpolateString)(nameTokens, ctx, localVariables);
        if (nameValue) {
            localVariables = {
                ...localVariables,
                name: {
                    key: 'name',
                    value: nameValue,
                },
            };
        }
    }
    let registryUrl = (0, common_1.interpolateString)((0, common_1.loadFromTokenMap)(ctx, 'registryUrl'), ctx, localVariables);
    if (registryUrl) {
        registryUrl = registryUrl.replace((0, regex_1.regEx)(/\\/g), '');
        try {
            const { host, protocol } = node_url_1.default.parse(registryUrl);
            if (host && protocol) {
                ctx.registryUrls.push({
                    registryUrl,
                    scope: isPluginRegistry(ctx) ? 'plugin' : 'dep',
                });
            }
        }
        catch (e) {
            // no-op
        }
    }
    return ctx;
}
function handleLibraryDep(ctx) {
    const groupIdTokens = (0, common_1.loadFromTokenMap)(ctx, 'groupId');
    const artifactIdTokens = (0, common_1.loadFromTokenMap)(ctx, 'artifactId');
    const groupId = (0, common_1.interpolateString)(groupIdTokens, ctx);
    const artifactId = (0, common_1.interpolateString)(artifactIdTokens, ctx);
    if (!groupId || !artifactId) {
        return ctx;
    }
    const aliasToken = (0, common_1.loadFromTokenMap)(ctx, 'alias')[0];
    const key = `libs.${aliasToken.value.replace((0, regex_1.regEx)(/[-_]/g), '.')}`;
    ctx.globalVars[key] = {
        key,
        value: `${groupId}:${artifactId}`,
        fileReplacePosition: aliasToken.offset,
        packageFile: ctx.packageFile,
    };
    if (ctx.tokenMap.version) {
        const version = (0, common_1.interpolateString)((0, common_1.loadFromTokenMap)(ctx, 'version'), ctx);
        if (version) {
            handleLongFormDep(ctx);
        }
    }
    return ctx;
}
function handleApplyFrom(ctx) {
    let scriptFile = (0, common_1.interpolateString)((0, common_1.loadFromTokenMap)(ctx, 'scriptFile'), ctx);
    if (!scriptFile) {
        return ctx;
    }
    if (ctx.tokenMap.parentPath) {
        const parentPath = (0, common_1.interpolateString)((0, common_1.loadFromTokenMap)(ctx, 'parentPath'), ctx);
        if (parentPath && scriptFile) {
            scriptFile = upath_1.default.join(parentPath, scriptFile);
        }
    }
    if (ctx.recursionDepth > 2) {
        logger_1.logger.debug(`Max recursion depth reached in script file: ${scriptFile}`);
        return ctx;
    }
    if (!(0, regex_1.regEx)(/\.gradle(\.kts)?$/).test(scriptFile)) {
        logger_1.logger.debug({ scriptFile }, `Only Gradle files can be included`);
        return ctx;
    }
    const scriptFilePath = (0, fs_1.getSiblingFileName)(ctx.packageFile, scriptFile);
    if (!ctx.fileContents[scriptFilePath]) {
        logger_1.logger.debug(`Failed to process included Gradle file ${scriptFilePath}`);
        return ctx;
    }
    const matchResult = parseGradle(
    // TODO #22198
    ctx.fileContents[scriptFilePath], ctx.globalVars, scriptFilePath, ctx.fileContents, ctx.recursionDepth + 1);
    ctx.deps.push(...matchResult.deps);
    ctx.globalVars = { ...ctx.globalVars, ...matchResult.vars };
    ctx.registryUrls.push(...matchResult.urls);
    return ctx;
}
function handleImplicitGradlePlugin(ctx) {
    const pluginName = (0, common_1.loadFromTokenMap)(ctx, 'pluginName')[0].value;
    const versionTokens = (0, common_1.loadFromTokenMap)(ctx, 'version');
    const versionValue = (0, common_1.interpolateString)(versionTokens, ctx);
    if (!versionValue) {
        return ctx;
    }
    const groupIdArtifactId = common_1.GRADLE_PLUGINS[pluginName][1];
    const dep = (0, utils_1.parseDependencyString)(`${groupIdArtifactId}:${versionValue}`);
    if (!dep) {
        return ctx;
    }
    dep.depName = pluginName;
    dep.packageName = groupIdArtifactId;
    dep.managerData = {
        fileReplacePosition: versionTokens[0].offset,
        packageFile: ctx.packageFile,
    };
    if (versionTokens.length > 1) {
        // = template string with multiple variables
        dep.skipReason = 'unspecified-version';
    }
    else if (versionTokens[0].type === 'symbol') {
        const varData = (0, common_1.findVariable)(versionTokens[0].value, ctx);
        if (varData) {
            dep.groupName = varData.key;
            dep.currentValue = varData.value;
            dep.managerData = {
                fileReplacePosition: varData.fileReplacePosition,
                packageFile: varData.packageFile,
            };
        }
    }
    ctx.deps.push(dep);
    return ctx;
}
//# sourceMappingURL=handlers.js.map