"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseChangelog = exports.getLocalChangelog = exports.breakingChangesInUpdate = exports.displayReleaseNotes = exports.getReleaseNotesForUpdate = void 0;
const clc = require("colorette");
const marked_1 = require("marked");
const path = require("path");
const semver = require("semver");
const TerminalRenderer = require("marked-terminal");
const Table = require("cli-table");
const extensionsApi_1 = require("./extensionsApi");
const localHelper_1 = require("./localHelper");
const logger_1 = require("../logger");
const refs = require("./refs");
const utils_1 = require("../utils");
marked_1.marked.setOptions({
    renderer: new TerminalRenderer(),
});
const EXTENSIONS_CHANGELOG = "CHANGELOG.md";
const VERSION_LINE_REGEX = /##.*(\d+\.\d+\.\d+(?:-((\d+|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(\d+|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?).*/;
async function getReleaseNotesForUpdate(args) {
    const releaseNotes = {};
    const filter = `id<="${args.toVersion}" AND id>"${args.fromVersion}"`;
    const extensionVersions = await (0, extensionsApi_1.listExtensionVersions)(args.extensionRef, filter);
    extensionVersions.sort((ev1, ev2) => {
        return -semver.compare(ev1.spec.version, ev2.spec.version);
    });
    for (const extensionVersion of extensionVersions) {
        if (extensionVersion.releaseNotes) {
            const version = refs.parse(extensionVersion.ref).version;
            releaseNotes[version] = extensionVersion.releaseNotes;
        }
    }
    return releaseNotes;
}
exports.getReleaseNotesForUpdate = getReleaseNotesForUpdate;
function displayReleaseNotes(releaseNotes, fromVersion) {
    const versions = [fromVersion].concat(Object.keys(releaseNotes));
    const breakingVersions = breakingChangesInUpdate(versions);
    const table = new Table({ head: ["Version", "What's New"], style: { head: ["yellow", "bold"] } });
    for (const [version, note] of Object.entries(releaseNotes)) {
        if (breakingVersions.includes(version)) {
            table.push([clc.yellow(clc.bold(version)), (0, marked_1.marked)(note)]);
        }
        else {
            table.push([version, (0, marked_1.marked)(note)]);
        }
    }
    logger_1.logger.info(clc.bold("What's new with this update:"));
    if (breakingVersions.length) {
        (0, utils_1.logLabeledWarning)("warning", "This is a major version update, which means it may contain breaking changes." +
            " Read the release notes carefully before continuing with this update.");
    }
    logger_1.logger.info(table.toString());
}
exports.displayReleaseNotes = displayReleaseNotes;
function breakingChangesInUpdate(versionsInUpdate) {
    const breakingVersions = [];
    const semvers = versionsInUpdate.map((v) => semver.parse(v)).sort(semver.compare);
    for (let i = 1; i < semvers.length; i++) {
        const hasMajorBump = semvers[i - 1].major < semvers[i].major;
        const hasMinorBumpInPreview = semvers[i - 1].major === 0 &&
            semvers[i].major === 0 &&
            semvers[i - 1].minor < semvers[i].minor;
        if (hasMajorBump || hasMinorBumpInPreview) {
            breakingVersions.push(semvers[i].raw);
        }
    }
    return breakingVersions;
}
exports.breakingChangesInUpdate = breakingChangesInUpdate;
function getLocalChangelog(directory) {
    const rawChangelog = (0, localHelper_1.readFile)(path.resolve(directory, EXTENSIONS_CHANGELOG));
    return parseChangelog(rawChangelog);
}
exports.getLocalChangelog = getLocalChangelog;
function parseChangelog(rawChangelog) {
    const changelog = {};
    let currentVersion = "";
    for (const line of rawChangelog.split("\n")) {
        const matches = line.match(VERSION_LINE_REGEX);
        if (matches) {
            currentVersion = matches[1];
        }
        else if (currentVersion) {
            if (!changelog[currentVersion]) {
                changelog[currentVersion] = line;
            }
            else {
                changelog[currentVersion] += `\n${line}`;
            }
        }
    }
    return changelog;
}
exports.parseChangelog = parseChangelog;
