"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.filterVersions = filterVersions;
const tslib_1 = require("tslib");
const semver_1 = tslib_1.__importDefault(require("semver"));
const error_messages_1 = require("../../../../constants/error-messages");
const logger_1 = require("../../../../logger");
const npmVersioning = tslib_1.__importStar(require("../../../../modules/versioning/npm"));
const pep440 = tslib_1.__importStar(require("../../../../modules/versioning/pep440"));
const poetryVersioning = tslib_1.__importStar(require("../../../../modules/versioning/poetry"));
const string_match_1 = require("../../../../util/string-match");
function isReleaseStable(release, versioning) {
    if (!versioning.isStable(release.version)) {
        return false;
    }
    if (release.isStable === false) {
        return false;
    }
    return true;
}
function filterVersions(config, currentVersion, latestVersion, releases, versioning) {
    const { ignoreUnstable, ignoreDeprecated, respectLatest, allowedVersions } = config;
    // istanbul ignore if: shouldn't happen
    if (!currentVersion) {
        return [];
    }
    // Leave only versions greater than current
    let filteredReleases = releases.filter((r) => versioning.isVersion(r.version) &&
        versioning.isGreaterThan(r.version, currentVersion));
    const currentRelease = releases.find((r) => versioning.isValid(r.version) &&
        versioning.isVersion(r.version) &&
        versioning.isValid(currentVersion) &&
        versioning.isVersion(currentVersion) &&
        versioning.equals(r.version, currentVersion));
    // Don't upgrade from non-deprecated to deprecated
    if (ignoreDeprecated && currentRelease && !currentRelease.isDeprecated) {
        filteredReleases = filteredReleases.filter((r) => {
            if (r.isDeprecated) {
                logger_1.logger.trace(`Skipping ${config.depName}@${r.version} because it is deprecated`);
                return false;
            }
            return true;
        });
    }
    if (allowedVersions) {
        const isAllowedPred = (0, string_match_1.getRegexPredicate)(allowedVersions);
        if (isAllowedPred) {
            filteredReleases = filteredReleases.filter(({ version }) => isAllowedPred(version));
        }
        else if (versioning.isValid(allowedVersions)) {
            filteredReleases = filteredReleases.filter((r) => versioning.matches(r.version, allowedVersions));
        }
        else if (config.versioning !== npmVersioning.id &&
            semver_1.default.validRange(allowedVersions)) {
            logger_1.logger.debug({ depName: config.depName }, 'Falling back to npm semver syntax for allowedVersions');
            filteredReleases = filteredReleases.filter((r) => semver_1.default.satisfies(semver_1.default.valid(r.version)
                ? r.version
                : /* istanbul ignore next: not reachable, but it's safer to preserve it */ semver_1.default.coerce(r.version), allowedVersions));
        }
        else if (config.versioning === poetryVersioning.id &&
            pep440.isValid(allowedVersions)) {
            logger_1.logger.debug({ depName: config.depName }, 'Falling back to pypi syntax for allowedVersions');
            filteredReleases = filteredReleases.filter((r) => pep440.matches(r.version, allowedVersions));
        }
        else {
            const error = new Error(error_messages_1.CONFIG_VALIDATION);
            error.validationSource = 'config';
            error.validationError = 'Invalid `allowedVersions`';
            error.validationMessage =
                'The following allowedVersions does not parse as a valid version or range: ' +
                    JSON.stringify(allowedVersions);
            throw error;
        }
    }
    if (config.followTag) {
        return filteredReleases;
    }
    if (respectLatest &&
        latestVersion &&
        !versioning.isGreaterThan(currentVersion, latestVersion)) {
        filteredReleases = filteredReleases.filter((r) => !versioning.isGreaterThan(r.version, latestVersion));
    }
    if (!ignoreUnstable) {
        return filteredReleases;
    }
    if (currentRelease && isReleaseStable(currentRelease, versioning)) {
        return filteredReleases.filter((r) => isReleaseStable(r, versioning));
    }
    const currentMajor = versioning.getMajor(currentVersion);
    const currentMinor = versioning.getMinor(currentVersion);
    const currentPatch = versioning.getPatch(currentVersion);
    return filteredReleases.filter((r) => {
        if (isReleaseStable(r, versioning)) {
            return true;
        }
        const major = versioning.getMajor(r.version);
        if (major !== currentMajor) {
            return false;
        }
        if (versioning.allowUnstableMajorUpgrades) {
            return true;
        }
        const minor = versioning.getMinor(r.version);
        const patch = versioning.getPatch(r.version);
        return minor === currentMinor && patch === currentPatch;
    });
}
//# sourceMappingURL=filter.js.map