"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.printUpdateDetails = exports.checkForUpdate = void 0;
const path = require("path");
const fs = require("fs");
const console_1 = require("./console");
const https = require("https");
function checkForUpdate() {
    return __awaiter(this, void 0, void 0, function* () {
        process.stdout.write(console_1.cgreen `⇢` + ` Checking whether newer version is available... `);
        try {
            const packageJsonContent = fs.readFileSync(path.join(__dirname, '..', '..', 'package.json'), 'utf-8');
            const packageJson = JSON.parse(packageJsonContent);
            const currentVersion = Version.parse(packageJson.version);
            if (!currentVersion) {
                process.stdout.write(console_1.RED_CROSS + '\n');
                console_1.debug(`[UpdateCheck] Could not check whether a newer version is available, continuing...`);
                return undefined;
            }
            const remoteVersion = yield getRemoteVersionFromRegistry(packageJson.name);
            if (!remoteVersion) {
                process.stdout.write(console_1.RED_CROSS + '\n');
                console_1.debug(`[UpdateCheck] Could not check whether a newer version is available, continuing...`);
                return undefined;
            }
            process.stdout.write(console_1.GREEN_CHECK + '\n');
            if (remoteVersion.isNewerThan(currentVersion)) {
                return {
                    installedVersion: currentVersion,
                    availableVersion: remoteVersion,
                };
            }
        }
        catch (e) {
            process.stdout.write(console_1.RED_CROSS + '\n');
            console_1.debug(`[UpdateCheck] Failed to check whether an update is available, continuing...`);
            console_1.debug(e);
        }
        return undefined;
    });
}
exports.checkForUpdate = checkForUpdate;
function printUpdateDetails(updateDetails) {
    if (!updateDetails) {
        return;
    }
    const installed = updateDetails.installedVersion.toString().padStart(8);
    const available = updateDetails.availableVersion.toString().padEnd(8);
    console.log();
    console.log(console_1.cgreen `!---------------------------------------------!`);
    console.log(console_1.cgreen `! A newer version of @cplace/asc is available !`);
    console.log(console_1.cgreen `! >> ${installed} -> ${available}                     !`);
    console.log(console_1.cgreen `! -> Please update to the latest version:     !`);
    console.log(console_1.cgreen `!    npm install -g @cplace/asc               !`);
    console.log(console_1.cgreen `!---------------------------------------------!`);
    console.log();
}
exports.printUpdateDetails = printUpdateDetails;
function getRemoteVersionFromRegistry(packageName) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const p = new Promise((resolve, reject) => {
                const req = https.request({
                    method: 'GET',
                    hostname: 'registry.npmjs.org',
                    path: `/-/package/${packageName}/dist-tags`,
                    timeout: 2000,
                }, (res) => {
                    let data = '';
                    res.on('data', (chunk) => {
                        data += chunk;
                    });
                    res.on('end', () => {
                        resolve(data);
                    });
                });
                req.on('socket', (socket) => {
                    socket.setTimeout(2000);
                    socket.on('timeout', () => {
                        req.abort();
                    });
                });
                req.on('error', (err) => {
                    reject(err);
                });
                req.end();
            });
            const body = yield p;
            const content = JSON.parse(body);
            return Version.parse(content.latest);
        }
        catch (e) {
            console_1.debug(e);
            return null;
        }
    });
}
class Version {
    constructor(major, minor, patch) {
        this.major = major;
        this.minor = minor;
        this.patch = patch;
    }
    static parse(version) {
        const parts = version.split('.');
        const segments = [-1, -1, -1];
        for (let i = 0; i < parts.length; i++) {
            try {
                segments[i] = parseInt(parts[i], 10);
            }
            catch (e) {
                return null;
            }
        }
        return new Version(segments[0], segments[1], segments[2]);
    }
    isNewerThan(other) {
        if (this.major > other.major) {
            return true;
        }
        else if (this.major < other.major) {
            return false;
        }
        else if (this.minor > other.minor) {
            return true;
        }
        else if (this.minor < other.minor) {
            return false;
        }
        else {
            return this.patch > other.patch;
        }
    }
    toString() {
        return `${this.major || 0}.${this.minor || 0}.${this.patch || 0}`;
    }
}
//# sourceMappingURL=check-update.js.map