"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const dns_1 = require("dns");
const extension_1 = require("@microsoft.azure/extension");
const os_1 = require("os");
const path_1 = require("path");
const tasks_1 = require("@microsoft.azure/tasks");
const semver = require("semver");
const async_io_1 = require("@microsoft.azure/async-io");
const fs_1 = require("fs");
const os_2 = require("os");
exports.pkgVersion = require(`${__dirname}/../package.json`).version;
process.env["autorest.home"] = process.env["autorest.home"] || os_1.homedir();
try {
    fs_1.rmdirSync(fs_1.mkdtempSync(path_1.join(process.env["autorest.home"], 'temp')));
}
catch {
    // hmm. the home  directory isn't writable. let's fallback to $tmp
    process.env["autorest.home"] = os_2.tmpdir();
}
exports.rootFolder = path_1.join(process.env["autorest.home"], ".autorest");
const args = global.__args || {};
exports.extensionManager = extension_1.ExtensionManager.Create(exports.rootFolder);
exports.corePackage = "@microsoft.azure/autorest-core"; // autorest-core"
const basePkgVersion = exports.pkgVersion.indexOf("-") > -1 ? exports.pkgVersion.substring(0, exports.pkgVersion.indexOf("-")) : exports.pkgVersion;
const versionRange = `^${basePkgVersion}`; // the version range of the core package required.
exports.networkEnabled = new Promise((r, j) => {
    dns_1.lookup("8.8.8.8", 4, (err, address, family) => {
        r(err ? false : true);
    });
});
async function availableVersions() {
    if (await exports.networkEnabled) {
        try {
            const vers = (await (await exports.extensionManager).getPackageVersions(exports.corePackage)).sort((b, a) => semver.compare(a, b));
            const result = new Array();
            for (const ver of vers) {
                if (semver.satisfies(ver, versionRange)) {
                    result.push(ver);
                }
            }
            return result;
        }
        catch (e) {
            console.info(`No available versions of package ${exports.corePackage} found.`);
        }
    }
    else {
        console.info(`Skipping getting available versions because network is not detected.`);
    }
    return [];
}
exports.availableVersions = availableVersions;
;
async function installedCores() {
    const extensions = await (await exports.extensionManager).getInstalledExtensions();
    const result = (extensions.length > 0) ? extensions.filter(ext => ext.name === exports.corePackage && semver.satisfies(ext.version, versionRange)) : new Array();
    return result.sort((a, b) => semver.compare(b.version, a.version));
}
exports.installedCores = installedCores;
;
function resolvePathForLocalVersion(requestedVersion) {
    try {
        return requestedVersion ? path_1.resolve(requestedVersion) : path_1.dirname(require.resolve("@microsoft.azure/autorest-core/package.json"));
    }
    catch (e) {
    }
    return null;
}
exports.resolvePathForLocalVersion = resolvePathForLocalVersion;
async function tryRequire(localPath, entrypoint) {
    try {
        const ep = await resolveEntrypoint(localPath, entrypoint);
        if (ep) {
            return require(await resolveEntrypoint(localPath, entrypoint));
        }
    }
    catch (E) {
        console.log(E);
    }
    return null;
}
exports.tryRequire = tryRequire;
async function resolveEntrypoint(localPath, entrypoint) {
    try {
        // did they specify the package directory directly 
        if (await async_io_1.isDirectory(localPath)) {
            const pkg = require(`${localPath}/package.json`);
            if (pkg.name === exports.corePackage) {
                switch (entrypoint) {
                    case 'main':
                    case 'main.js':
                        entrypoint = pkg.main;
                        break;
                    case 'language-service':
                    case 'language-service.js':
                    case 'autorest-language-service':
                        entrypoint = pkg.bin["autorest-language-service"];
                        break;
                    case 'autorest':
                    case 'autorest-core':
                    case 'app.js':
                    case 'app':
                        entrypoint = pkg.bin["autorest-core"];
                        break;
                    case 'module':
                        // special case: look for the main entrypoint
                        // but return the module folder
                        if (await async_io_1.isFile(`${localPath}/${pkg.main}`)) {
                            return localPath;
                        }
                }
                const path = `${localPath}/${entrypoint}`;
                if (await async_io_1.isFile(path)) {
                    return path;
                }
            }
        }
    }
    catch (e) {
    }
    return null;
}
exports.resolveEntrypoint = resolveEntrypoint;
async function ensureAutorestHome() {
    await async_io_1.mkdir(exports.rootFolder);
}
exports.ensureAutorestHome = ensureAutorestHome;
async function selectVersion(requestedVersion, force, minimumVersion) {
    const installedVersions = await installedCores();
    let currentVersion = installedVersions[0] || null;
    // the consumer can say I want the latest-installed, but at least XXX.XXX
    if (minimumVersion && currentVersion && !semver.satisfies(currentVersion.version, minimumVersion)) {
        currentVersion = null;
    }
    if (currentVersion) {
        if (args.debug) {
            console.log(`The most recent installed version is ${currentVersion.version}`);
        }
        if (requestedVersion === "latest-installed" || (requestedVersion === 'latest' && false == await exports.networkEnabled)) {
            if (args.debug) {
                console.log(`requesting current version '${currentVersion.version}'`);
            }
            requestedVersion = currentVersion.version;
        }
    }
    else {
        if (args.debug) {
            console.log(`No ${exports.corePackage} is installed.`);
        }
    }
    let selectedVersion = null;
    for (const each of installedVersions) {
        if (semver.satisfies(each.version, requestedVersion)) {
            selectedVersion = each;
        }
    }
    // is the requested version installed?
    if (!selectedVersion || force) {
        if (!force) {
            if (args.debug) {
                console.log(`${requestedVersion} was not satisfied directly by a previous installation.`);
            }
        }
        // if it's not a file, and the network isn't available, we can't continue.
        if (!await async_io_1.isFile(requestedVersion) && !(await exports.networkEnabled)) {
            // no network enabled.
            throw new tasks_1.Exception(`Network access is not available, requested version '${requestedVersion}' is not installed. `);
        }
        // after this point, latest-installed must mean latest.
        if (requestedVersion === 'latest-installed') {
            requestedVersion = 'latest';
        }
        // if they have requested 'latest' -- they really mean latest with same major version number
        if (requestedVersion === 'latest') {
            requestedVersion = versionRange;
        }
        const pkg = await (await exports.extensionManager).findPackage(exports.corePackage, requestedVersion);
        if (pkg) {
            if (args.debug) {
                console.log(`Selected package: ${pkg.name}@${pkg.version} => ${pkg.resolvedInfo.rawSpec} `);
            }
        }
        else {
            throw new tasks_1.Exception(`Unable to find a valid AutoRest Core package for '${requestedVersion}'.`);
        }
        // pkg.version == the actual version 
        // check if it's installed already.
        selectedVersion = await (await exports.extensionManager).getInstalledExtension(exports.corePackage, pkg.version);
        if (!selectedVersion || force) {
            // this will throw if there is an issue with installing the extension.
            if (args.debug) {
                console.log(`**Installing package** ${exports.corePackage}@${pkg.version}\n[This will take a few moments...]`);
            }
            selectedVersion = await (await exports.extensionManager).installPackage(pkg, force, 5 * 60 * 1000, installer => installer.Message.Subscribe((s, m) => { if (args.debug)
                console.log(`Installer: ${m}`); }));
            if (args.debug) {
                console.log(`Extension location: ${selectedVersion.packageJsonPath}`);
            }
        }
        else {
            if (args.debug) {
                console.log(`AutoRest Core ${pkg.version} is available at ${selectedVersion.modulePath}`);
            }
        }
    }
    return selectedVersion;
}
exports.selectVersion = selectVersion;
//# sourceMappingURL=autorest-as-a-service.js.map