"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.doAutoReplace = exports.checkBranchDepsMatchBaseDeps = exports.confirmIfDepUpdated = void 0;
// TODO #7154
const error_messages_1 = require("../../../../constants/error-messages");
const logger_1 = require("../../../../logger");
const manager_1 = require("../../../../modules/manager");
const fs_1 = require("../../../../util/fs");
const regex_1 = require("../../../../util/regex");
const string_1 = require("../../../../util/string");
const template_1 = require("../../../../util/template");
async function confirmIfDepUpdated(upgrade, newContent) {
    const { manager, packageFile, newValue, newDigest, depIndex, currentDigest, pinDigests, } = upgrade;
    const extractPackageFile = (0, manager_1.get)(manager, 'extractPackageFile');
    let newUpgrade;
    try {
        const newExtract = await extractPackageFile(newContent, packageFile, upgrade);
        // istanbul ignore if
        if (!newExtract) {
            // TODO: fix types (#7154)
            logger_1.logger.debug(`Could not extract ${packageFile}`);
            return false;
        }
        newUpgrade = newExtract.deps[depIndex];
    }
    catch (err) /* istanbul ignore next */ {
        logger_1.logger.debug({ manager, packageFile, err }, 'Failed to parse newContent');
    }
    if (!newUpgrade) {
        logger_1.logger.debug(`No newUpgrade in ${packageFile}`);
        return false;
    }
    if (upgrade.depName !== newUpgrade.depName) {
        logger_1.logger.debug({
            manager,
            packageFile,
            currentDepName: upgrade.depName,
            newDepName: newUpgrade.depName,
        }, 'depName mismatch');
        return false;
    }
    if (newValue && newUpgrade.currentValue !== newValue) {
        logger_1.logger.debug({
            manager,
            packageFile,
            expectedValue: newValue,
            foundValue: newUpgrade.currentValue,
        }, 'Value mismatch');
        return false;
    }
    if (!newDigest) {
        return true;
    }
    if (newUpgrade.currentDigest === newDigest) {
        return true;
    }
    if (!currentDigest && !pinDigests) {
        return true;
    }
    // istanbul ignore next
    return false;
}
exports.confirmIfDepUpdated = confirmIfDepUpdated;
function getDepsSignature(deps) {
    // TODO: types (#7154)
    return deps.map((dep) => `${dep.depName}${dep.packageName}`).join(',');
}
async function checkBranchDepsMatchBaseDeps(upgrade, branchContent) {
    const { baseDeps, manager, packageFile } = upgrade;
    const extractPackageFile = (0, manager_1.get)(manager, 'extractPackageFile');
    try {
        const res = await extractPackageFile(branchContent, packageFile, upgrade);
        const branchDeps = res.deps;
        return getDepsSignature(baseDeps) === getDepsSignature(branchDeps);
    }
    catch (err) /* istanbul ignore next */ {
        logger_1.logger.info({ manager, packageFile }, 'Failed to parse branchContent - rebasing');
        return false;
    }
}
exports.checkBranchDepsMatchBaseDeps = checkBranchDepsMatchBaseDeps;
async function checkExistingBranch(upgrade, existingContent) {
    const { packageFile, depName } = upgrade;
    if (!(await checkBranchDepsMatchBaseDeps(upgrade, existingContent))) {
        logger_1.logger.debug({ packageFile, depName }, 'Rebasing branch after deps list has changed');
        return null;
    }
    if (!(await confirmIfDepUpdated(upgrade, existingContent))) {
        logger_1.logger.debug({ packageFile, depName }, 'Rebasing after outdated branch dep found');
        return null;
    }
    // TODO: fix types (#7154)
    logger_1.logger.debug(`Branch dep ${depName} in ${packageFile} is already updated`);
    return existingContent;
}
async function doAutoReplace(upgrade, existingContent, reuseExistingBranch) {
    const { packageFile, depName, currentValue, newValue, currentDigest, newDigest, autoReplaceStringTemplate, } = upgrade;
    if (reuseExistingBranch) {
        return await checkExistingBranch(upgrade, existingContent);
    }
    const replaceString = upgrade.replaceString ?? currentValue;
    logger_1.logger.trace({ depName, replaceString }, 'autoReplace replaceString');
    let searchIndex = existingContent.indexOf(replaceString);
    if (searchIndex === -1) {
        logger_1.logger.info({ packageFile, depName, existingContent, replaceString }, 'Cannot find replaceString in current file content. Was it already updated?');
        return existingContent;
    }
    try {
        let newString;
        if (autoReplaceStringTemplate) {
            newString = (0, template_1.compile)(autoReplaceStringTemplate, upgrade, false);
        }
        else {
            newString = replaceString;
            if (currentValue && newValue) {
                newString = newString.replace((0, regex_1.regEx)((0, regex_1.escapeRegExp)(currentValue), 'g'), newValue);
            }
            if (currentDigest && newDigest) {
                newString = newString.replace((0, regex_1.regEx)((0, regex_1.escapeRegExp)(currentDigest), 'g'), newDigest);
            }
        }
        logger_1.logger.debug({ packageFile, depName }, `Starting search at index ${searchIndex}`);
        let newContent = existingContent;
        // Iterate through the rest of the file
        for (; searchIndex < newContent.length; searchIndex += 1) {
            // First check if we have a hit for the old version
            if ((0, string_1.matchAt)(existingContent, searchIndex, replaceString)) {
                logger_1.logger.debug({ packageFile, depName }, `Found match at index ${searchIndex}`);
                // Now test if the result matches
                newContent = (0, string_1.replaceAt)(newContent, searchIndex, replaceString, newString);
                await (0, fs_1.writeLocalFile)(upgrade.packageFile, newContent);
                if (await confirmIfDepUpdated(upgrade, newContent)) {
                    return newContent;
                }
                await (0, fs_1.writeLocalFile)(upgrade.packageFile, existingContent);
                newContent = existingContent;
            }
        }
    }
    catch (err) /* istanbul ignore next */ {
        logger_1.logger.debug({ packageFile, depName, err }, 'doAutoReplace error');
    }
    // istanbul ignore next
    throw new Error(error_messages_1.WORKER_FILE_UPDATE_FAILED);
}
exports.doAutoReplace = doAutoReplace;
//# sourceMappingURL=auto-replace.js.map