"use strict";
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const cwd = process.cwd();
// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
if (!String.prototype.padEnd) {
    String.prototype.padEnd = function padEnd(targetLength, padString) {
        targetLength = targetLength >> 0; // floor if number or convert non-number to 0;
        padString = String(padString || ' ');
        if (this.length > targetLength) {
            return String(this);
        }
        else {
            targetLength = targetLength - this.length;
            if (targetLength > padString.length) {
                padString += padString.repeat(targetLength / padString.length); // append to original to ensure we are longer than needed
            }
            return String(this) + padString.slice(0, targetLength);
        }
    };
}
const async_io_1 = require("@microsoft.azure/async-io");
const tasks_1 = require("@microsoft.azure/tasks");
const chalk_1 = require("chalk");
const path_1 = require("path");
const semver_1 = require("semver");
const autorest_as_a_service_1 = require("./autorest-as-a-service");
const coloring_1 = require("./coloring");
// aliases, round one.
if (process.argv.indexOf('--no-upgrade-check') !== -1) {
    process.argv.push('--skip-upgrade-check');
}
if (process.argv.indexOf('--json') !== -1) {
    process.argv.push('--message-format=json');
}
if (process.argv.indexOf('--yaml') !== -1) {
    process.argv.push('--message-format=yaml');
}
function parseArgs(autorestArgs) {
    const result = {};
    for (const arg of autorestArgs) {
        const match = /^--([^=:]+)([=:](.+))?$/g.exec(arg);
        if (match) {
            const key = match[1];
            let rawValue = match[3] || 'true';
            if (rawValue.startsWith('.')) {
                // starts with a . or .. -> this is a relative path to current directory
                rawValue = path_1.join(cwd, rawValue);
            }
            let value;
            try {
                value = JSON.parse(rawValue);
                // restrict allowed types (because with great type selection comes great responsibility)
                if (typeof value !== 'string' && typeof value !== 'boolean') {
                    value = rawValue;
                }
            }
            catch (e) {
                value = rawValue;
            }
            result[key] = value;
        }
    }
    return result;
}
const args = parseArgs(process.argv);
global.__args = args;
// aliases
args['info'] = args['info'] || args['list-installed'];
args['preview'] = args['preview'] || args['prerelease'];
// Suppress the banner if the message-format is set to something other than regular.
if ((!args['message-format']) || args['message-format'] === 'regular') {
    console.log(chalk_1.default.green.bold.underline(`AutoRest code generation utility [version: ${chalk_1.default.white.bold(autorest_as_a_service_1.pkgVersion)}; node: ${chalk_1.default.white.bold(process.version)}]`));
    console.log(coloring_1.color(`(C) 2018 **Microsoft Corporation.**`));
    console.log(chalk_1.default.blue.bold.underline(`https://aka.ms/autorest`));
}
// argument tweakin'
const preview = args.preview;
args.info = (args.version === '' || args.version === true) || args.info; // show --info if they use unparameterized --version.
const listAvailable = args['list-available'] || false;
const force = args.force || false;
/** Check if there is an update for the bootstrapper available. */
const checkBootstrapper = new tasks_1.LazyPromise(async () => {
    if (await autorest_as_a_service_1.networkEnabled && !args['skip-upgrade-check']) {
        try {
            const pkg = await (await autorest_as_a_service_1.extensionManager).findPackage('autorest', preview ? 'preview' : 'latest');
            if (semver_1.gt(pkg.version, autorest_as_a_service_1.pkgVersion)) {
                console.log(coloring_1.color(`\n## There is a new version of AutoRest available (${pkg.version}).\n > You can install the newer version with with \`npm install -g autorest@${preview ? 'preview' : 'latest'}\`\n`));
            }
        }
        catch (e) {
            // no message then.
        }
    }
});
/** Shows the valid available autorest core packages. */
async function showAvailableCores() {
    let table = '';
    let max = 10;
    const cores = await autorest_as_a_service_1.availableVersions();
    for (const v of cores) {
        max--;
        table += `\n ${chalk_1.default.cyan.bold(autorest_as_a_service_1.corePackage.padEnd(30, ' '))} ${chalk_1.default.grey.bold(v.padEnd(14, ' '))} `;
        if (!max) {
            break;
        }
    }
    if (args.json) {
        console.log(JSON.stringify(cores, null, '  '));
    }
    else {
        if (table) {
            console.log(`${chalk_1.default.green.bold.underline(' Extension Name'.padEnd(30, ' '))}  ${chalk_1.default.green.bold.underline('Version'.padEnd(14, ' '))}\n${table}`);
        }
    }
    return 0;
}
/** Shows all the autorest extensions that are installed. */
async function showInstalledExtensions() {
    const extensions = await (await autorest_as_a_service_1.extensionManager).getInstalledExtensions();
    let table = '';
    if (extensions.length > 0) {
        for (const extension of extensions) {
            table += `\n ${chalk_1.default.cyan((extension.name === autorest_as_a_service_1.corePackage ? 'core' : 'extension').padEnd(10))} ${chalk_1.default.cyan.bold(extension.name.padEnd(40))} ${chalk_1.default.cyan(extension.version.padEnd(12))} ${chalk_1.default.cyan(extension.location)}`;
        }
    }
    if (args.json) {
        console.log(JSON.stringify(extensions, null, '  '));
    }
    else {
        if (table) {
            console.log(coloring_1.color(`\n\n# Showing All Installed Extensions\n\n ${chalk_1.default.underline('Type'.padEnd(10))} ${chalk_1.default.underline('Extension Name'.padEnd(40))} ${chalk_1.default.underline('Version'.padEnd(12))} ${chalk_1.default.underline('Location')} ${table}\n\n`));
        }
        else {
            console.log(coloring_1.color('\n\n# Showing All Installed Extensions\n\n > No Extensions are currently installed.\n\n'));
        }
    }
    return 0;
}
/** Main Entrypoint for AutoRest Bootstrapper */
async function main() {
    try {
        // did they ask for what is available?
        if (listAvailable) {
            process.exit(await showAvailableCores());
        }
        // show what we have.
        if (args.info) {
            process.exit(await showInstalledExtensions());
        }
        try {
            /* make sure we have a .autorest folder */
            await autorest_as_a_service_1.ensureAutorestHome();
            // if we have an autorest home folder, --reset may mean something.
            // if it's not there, --reset won't do anything.
            if (args.reset) {
                if (args.debug) {
                    console.log(`Resetting autorest extension folder '${autorest_as_a_service_1.rootFolder}'`);
                }
                try {
                    await (await autorest_as_a_service_1.extensionManager).reset();
                }
                catch (e) {
                    console.log(coloring_1.color('\n\n## The AutoRest extension folder appears to be locked.\nDo you have a process that is currently using AutoRest (perhaps the vscode extension?).\n\nUnable to reset the extension folder, exiting.'));
                    process.exit(10);
                }
            }
        }
        catch {
            // We have a chance to fail again later if this proves problematic.
        }
        let requestedVersion = args.version || (args.latest && 'latest') || (args.preview && 'preview') || 'latest-installed';
        // check to see if local installed core is available.
        const localVersion = autorest_as_a_service_1.resolvePathForLocalVersion(args.version ? requestedVersion : null);
        // try to use a specified folder or one in node_modules if it is there.
        process.chdir(cwd);
        if (await autorest_as_a_service_1.tryRequire(localVersion, 'app.js')) {
            return;
        }
        // if the resolved local version is actually a file, we'll try that as a package when we get there.
        if (await async_io_1.isFile(localVersion)) {
            // this should try to install the file.
            if (args.debug) {
                console.log(`Found local core package file: '${localVersion}'`);
            }
            requestedVersion = localVersion;
        }
        // failing that, we'll continue on and see if NPM can do something with the version.
        if (args.debug) {
            console.log(`Network Enabled: ${await autorest_as_a_service_1.networkEnabled}`);
        }
        // wait for the bootstrapper check to finish.
        await checkBootstrapper;
        // logic to resolve and optionally install a autorest core package.
        // will throw if it's not doable.
        const selectedVersion = await autorest_as_a_service_1.selectVersion(requestedVersion, force);
        // let's strip the extra stuff from the command line before we require the core module.
        const oldArgs = process.argv;
        const newArgs = new Array();
        for (const each of process.argv) {
            let keep = true;
            for (const discard of ['--version', '--list-installed', '--list-available', '--reset', '--latest', '--latest-release', '--runtime-id']) {
                if (each === discard || each.startsWith(`${discard}=`) || each.startsWith(`${discard}:`)) {
                    keep = false;
                }
            }
            if (keep) {
                newArgs.push(each);
            }
        }
        process.argv = newArgs;
        // use this to make the core aware that this run may be legal even without any inputs
        // this is a valid scenario for "preparation calls" to autorest like `autorest --reset` or `autorest --latest`
        if (args.reset || args.latest || args.version == 'latest') {
            // if there is *any* other argument left, that's an indicator that the core is supposed to do something
            process.argv.push('--allow-no-input');
        }
        if (args.debug) {
            console.log(`Starting ${autorest_as_a_service_1.corePackage} from ${await selectedVersion.location}`);
        }
        process.chdir(cwd);
        const result = await autorest_as_a_service_1.tryRequire(await selectedVersion.modulePath, 'app.js');
        if (!result) {
            throw new Error(`Unable to start AutoRest Core from ${await selectedVersion.modulePath}`);
        }
    }
    catch (exception) {
        console.log(chalk_1.default.redBright('Failure:'));
        console.error(chalk_1.default.bold(exception));
        console.error(chalk_1.default.bold(exception.stack));
        process.exit(1);
    }
}
main();
//# sourceMappingURL=app.js.map