"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConanDatasource = void 0;
const tslib_1 = require("tslib");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const js_yaml_1 = require("js-yaml");
const logger_1 = require("../../../logger");
const decorator_1 = require("../../../util/cache/package/decorator");
const github_1 = require("../../../util/http/github");
const url_1 = require("../../../util/url");
const allVersioning = tslib_1.__importStar(require("../../versioning"));
const datasource_1 = require("../datasource");
const util_1 = require("../util");
const common_1 = require("./common");
class ConanDatasource extends datasource_1.Datasource {
    static id = common_1.datasource;
    defaultRegistryUrls = [common_1.defaultRegistryUrl];
    caching = true;
    registryStrategy = 'merge';
    githubHttp;
    constructor(id = ConanDatasource.id) {
        super(id);
        this.githubHttp = new github_1.GithubHttp(id);
    }
    async getConanCenterReleases(conanName, userAndChannel) {
        if (userAndChannel && userAndChannel !== '@_/_') {
            logger_1.logger.debug({ conanName, userAndChannel }, 'User/channel not supported for Conan Center lookups');
            return null;
        }
        const url = `https://api.github.com/repos/conan-io/conan-center-index/contents/recipes/${conanName}/config.yml`;
        const res = await this.githubHttp.get(url, {
            headers: { accept: 'application/vnd.github.v3.raw' },
        });
        const doc = (0, js_yaml_1.load)(res.body, {
            json: true,
        });
        return {
            releases: Object.keys(doc?.versions ?? {}).map((version) => ({
                version,
            })),
        };
    }
    async getDigest({ registryUrl, packageName }, newValue) {
        if (is_1.default.undefined(newValue) || is_1.default.undefined(registryUrl)) {
            return null;
        }
        const url = (0, url_1.ensureTrailingSlash)(registryUrl);
        const conanPackage = (0, common_1.getConanPackage)(packageName);
        const revisionLookUp = (0, url_1.joinUrlParts)(url, 'v2/conans/', conanPackage.conanName, newValue, conanPackage.userAndChannel, '/revisions');
        const revisionRep = await this.http.getJson(revisionLookUp);
        const revisions = revisionRep?.body.revisions;
        return revisions?.[0].revision ?? null;
    }
    async getReleases({ registryUrl, packageName, }) {
        const conanPackage = (0, common_1.getConanPackage)(packageName);
        const userAndChannel = '@' + conanPackage.userAndChannel;
        if (is_1.default.string(registryUrl) &&
            (0, url_1.ensureTrailingSlash)(registryUrl) === common_1.defaultRegistryUrl) {
            return this.getConanCenterReleases(conanPackage.conanName, userAndChannel);
        }
        logger_1.logger.trace({ packageName, registryUrl }, 'Looking up conan api dependency');
        if (registryUrl) {
            const url = (0, url_1.ensureTrailingSlash)(registryUrl);
            const lookupUrl = (0, url_1.joinUrlParts)(url, `v2/conans/search?q=${conanPackage.conanName}`);
            try {
                const rep = await this.http.getJson(lookupUrl);
                const versions = rep?.body;
                if (versions) {
                    logger_1.logger.trace({ lookupUrl }, 'Got conan api result');
                    const dep = { releases: [] };
                    for (const resultString of Object.values(versions.results ?? {})) {
                        const fromMatch = common_1.conanDatasourceRegex.exec(resultString);
                        if (fromMatch?.groups?.version && fromMatch?.groups?.userChannel) {
                            const version = fromMatch.groups.version;
                            if (fromMatch.groups.userChannel === userAndChannel) {
                                const result = {
                                    version,
                                };
                                dep.releases.push(result);
                            }
                        }
                    }
                    try {
                        if ((0, util_1.isArtifactoryServer)(rep)) {
                            const conanApiRegexp = /(?<host>.*)\/artifactory\/api\/conan\/(?<repo>[^/]+)/;
                            const groups = url.match(conanApiRegexp)?.groups;
                            if (!groups) {
                                return dep;
                            }
                            const semver = allVersioning.get('semver');
                            const sortedReleases = dep.releases
                                .filter((release) => semver.isVersion(release.version))
                                .sort((a, b) => semver.sortVersions(a.version, b.version));
                            const latestVersion = sortedReleases.at(-1)?.version;
                            if (!latestVersion) {
                                return dep;
                            }
                            logger_1.logger.debug(`Conan package ${packageName} has latest version ${latestVersion}`);
                            const latestRevisionUrl = (0, url_1.joinUrlParts)(url, `v2/conans/${conanPackage.conanName}/${latestVersion}/${conanPackage.userAndChannel}/latest`);
                            const revResp = await this.http.getJson(latestRevisionUrl);
                            const packageRev = revResp.body.revision;
                            const [user, channel] = conanPackage.userAndChannel.split('/');
                            const packageUrl = (0, url_1.joinUrlParts)(`${groups.host}/artifactory/api/storage/${groups.repo}`, `${user}/${conanPackage.conanName}/${latestVersion}/${channel}/${packageRev}/export/conanfile.py?properties=conan.package.url`);
                            const packageUrlResp = await this.http.getJson(packageUrl);
                            if (packageUrlResp.body.properties &&
                                'conan.package.url' in packageUrlResp.body.properties) {
                                const conanPackageUrl = packageUrlResp.body.properties['conan.package.url'][0];
                                dep.sourceUrl = conanPackageUrl;
                            }
                        }
                    }
                    catch (err) {
                        logger_1.logger.debug({ err }, "Couldn't determine Conan package url");
                    }
                    return dep;
                }
            }
            catch (err) {
                this.handleGenericErrors(err);
            }
        }
        return null;
    }
}
exports.ConanDatasource = ConanDatasource;
tslib_1.__decorate([
    (0, decorator_1.cache)({
        namespace: `datasource-${common_1.datasource}-revisions`,
        key: ({ registryUrl, packageName }, newValue) => 
        // TODO: types (#22198)
        `${registryUrl}:${packageName}:${newValue}`,
    })
], ConanDatasource.prototype, "getDigest", null);
tslib_1.__decorate([
    (0, decorator_1.cache)({
        namespace: `datasource-${common_1.datasource}`,
        key: ({ registryUrl, packageName }) => 
        // TODO: types (#22198)
        `${registryUrl}:${packageName}`,
    })
], ConanDatasource.prototype, "getReleases", null);
//# sourceMappingURL=index.js.map