"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getNewValue = void 0;
const tslib_1 = require("tslib");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const semver_1 = tslib_1.__importDefault(require("semver"));
const semver_utils_1 = tslib_1.__importDefault(require("semver-utils"));
const logger_1 = require("../../../logger");
const regex_1 = require("../../../util/regex");
const common_1 = require("../semver/common");
const { inc: increment, valid: isVersion, major, minor, patch, prerelease, satisfies, } = semver_1.default;
function replaceCaretValue(oldValue, newValue) {
    const toVersionMajor = major(newValue);
    const toVersionMinor = minor(newValue);
    const toVersionPatch = patch(newValue);
    const currentMajor = major(oldValue);
    const currentMinor = minor(oldValue);
    const currentPatch = patch(oldValue);
    const oldTuple = [currentMajor, currentMinor, currentPatch];
    const newTuple = [toVersionMajor, toVersionMinor, toVersionPatch];
    const resultTuple = [];
    let leadingZero = true;
    let needReplace = false;
    for (let idx = 0; idx < 3; idx += 1) {
        const oldVal = oldTuple[idx];
        const newVal = newTuple[idx];
        let leadingDigit = false;
        if (oldVal !== 0 || newVal !== 0) {
            if (leadingZero) {
                leadingZero = false;
                leadingDigit = true;
            }
        }
        if (leadingDigit && newVal > oldVal) {
            needReplace = true;
        }
        if (!needReplace && newVal < oldVal) {
            return newValue;
        }
        resultTuple.push(leadingDigit ? newVal : 0);
    }
    return needReplace ? resultTuple.join('.') : oldValue;
}
// TODO: #22198
function getNewValue({ currentValue, rangeStrategy, currentVersion, newVersion, }) {
    if (!['pin', 'update-lockfile'].includes(rangeStrategy) &&
        (0, common_1.isSemVerXRange)(currentValue)) {
        return null;
    }
    if (rangeStrategy === 'pin' || isVersion(currentValue)) {
        return newVersion;
    }
    if (rangeStrategy === 'update-lockfile') {
        if (satisfies(newVersion, currentValue)) {
            return currentValue;
        }
        return getNewValue({
            currentValue,
            rangeStrategy: 'replace',
            currentVersion,
            newVersion,
        });
    }
    const parsedRange = semver_utils_1.default.parseRange(currentValue);
    const element = parsedRange[parsedRange.length - 1];
    if (rangeStrategy === 'widen') {
        if (satisfies(newVersion, currentValue)) {
            return currentValue;
        }
        const newValue = getNewValue({
            currentValue,
            rangeStrategy: 'replace',
            currentVersion,
            newVersion,
        });
        if (element.operator?.startsWith('<')) {
            // TODO fix this
            const splitCurrent = currentValue.split(element.operator);
            splitCurrent.pop();
            // TODO: types (#22198)
            return `${splitCurrent.join(element.operator)}${newValue}`;
        }
        if (parsedRange.length > 1) {
            const previousElement = parsedRange[parsedRange.length - 2];
            if (previousElement.operator === '-') {
                const splitCurrent = currentValue.split('-');
                splitCurrent.pop();
                // TODO: types (#22198)
                return `${splitCurrent.join('-')}- ${newValue}`;
            }
            if (element.operator?.startsWith('>')) {
                logger_1.logger.warn(`Complex ranges ending in greater than are not supported`);
                return null;
            }
        }
        // TODO: types (#22198)
        return `${currentValue} || ${newValue}`;
    }
    const toVersionMajor = major(newVersion);
    const toVersionMinor = minor(newVersion);
    const toVersionPatch = patch(newVersion);
    const toNewVersion = prerelease(newVersion);
    const suffix = toNewVersion ? `-${toNewVersion[0]}` : '';
    // Simple range
    if (rangeStrategy === 'bump') {
        if (parsedRange.length === 1) {
            if (!element.operator) {
                return getNewValue({
                    currentValue,
                    rangeStrategy: 'replace',
                    currentVersion,
                    newVersion,
                });
            }
            if (element.operator === '^') {
                return `^${newVersion}`;
            }
            if (element.operator === '~') {
                return `~${newVersion}`;
            }
            if (element.operator === '=') {
                return `=${newVersion}`;
            }
            if (element.operator === '>=') {
                return currentValue.includes('>= ')
                    ? `>= ${newVersion}`
                    : `>=${newVersion}`;
            }
            if (element.operator.startsWith('<')) {
                return currentValue;
            }
        }
        else {
            return semver_utils_1.default
                .parseRange(currentValue)
                .map((x) => x.semver)
                .filter(is_1.default.string)
                .map((subRange) => {
                const bumpedSubRange = getNewValue({
                    currentValue: subRange,
                    rangeStrategy: 'bump',
                    currentVersion,
                    newVersion,
                });
                if (bumpedSubRange && satisfies(newVersion, bumpedSubRange)) {
                    return bumpedSubRange;
                }
                return getNewValue({
                    currentValue: subRange,
                    rangeStrategy: 'replace',
                    currentVersion,
                    newVersion,
                });
            })
                .filter((x) => x !== null && x !== '')
                .join(' ');
        }
        logger_1.logger.debug('Unsupported range type for rangeStrategy=bump: ' + currentValue);
        return null;
    }
    if (element.operator === '~>') {
        return `~> ${toVersionMajor}.${toVersionMinor}.0`;
    }
    if (element.operator === '^') {
        if (suffix.length || !currentVersion) {
            return `^${toVersionMajor}.${toVersionMinor}.${toVersionPatch}${suffix}`;
        }
        return `^${replaceCaretValue(currentVersion, newVersion)}`;
    }
    if (element.operator === '=') {
        return `=${newVersion}`;
    }
    if (element.operator === '~') {
        if (suffix.length) {
            return `~${toVersionMajor}.${toVersionMinor}.${toVersionPatch}${suffix}`;
        }
        return `~${toVersionMajor}.${toVersionMinor}.0`;
    }
    if (element.operator === '<=') {
        let res;
        if (!!element.patch || suffix.length) {
            res = `<=${newVersion}`;
        }
        else if (element.minor) {
            res = `<=${toVersionMajor}.${toVersionMinor}`;
        }
        else {
            res = `<=${toVersionMajor}`;
        }
        if (currentValue.includes('<= ')) {
            res = res.replace('<=', '<= ');
        }
        return res;
    }
    if (element.operator === '<') {
        let res;
        if (currentValue.endsWith('.0.0')) {
            const newMajor = toVersionMajor + 1;
            res = `<${newMajor}.0.0`;
        }
        else if (element.patch) {
            // TODO: types (#22198)
            res = `<${increment(newVersion, 'patch')}`;
        }
        else if (element.minor) {
            res = `<${toVersionMajor}.${toVersionMinor + 1}`;
        }
        else {
            res = `<${toVersionMajor + 1}`;
        }
        if (currentValue.includes('< ')) {
            res = res.replace((0, regex_1.regEx)(/</g), '< ');
        }
        return res;
    }
    if (!element.operator) {
        if (element.minor) {
            if (element.minor === 'x') {
                return `${toVersionMajor}.x`;
            }
            if (element.minor === '*') {
                return `${toVersionMajor}.*`;
            }
            if (element.patch === 'x') {
                return `${toVersionMajor}.${toVersionMinor}.x`;
            }
            if (element.patch === '*') {
                return `${toVersionMajor}.${toVersionMinor}.*`;
            }
            return `${toVersionMajor}.${toVersionMinor}`;
        }
        return `${toVersionMajor}`;
    }
    return newVersion;
}
exports.getNewValue = getNewValue;
//# sourceMappingURL=range.js.map