"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// load modules from static linker filesystem.
if (process.argv.indexOf("--no-static-loader") === -1 && process.env["no-static-loader"] === undefined && require('fs').existsSync('./static-loader.js')) {
    require('./static-loader.js').load(`${__dirname}/static_modules.fs`);
}
// everything else.
const autorest_as_a_service_1 = require("./autorest-as-a-service");
const path_1 = require("path");
/**
 * The Channel that a message is registered with.
 */
var Channel;
(function (Channel) {
    /** Information is considered the mildest of responses; not necesarily actionable. */
    Channel[Channel["Information"] = "information"] = "Information";
    /** Warnings are considered important for best practices, but not catastrophic in nature. */
    Channel[Channel["Warning"] = "warning"] = "Warning";
    /** Errors are considered blocking issues that block a successful operation.  */
    Channel[Channel["Error"] = "error"] = "Error";
    /** Debug messages are designed for the developer to communicate internal autorest implementation details. */
    Channel[Channel["Debug"] = "debug"] = "Debug";
    /** Verbose messages give the user additional clarity on the process. */
    Channel[Channel["Verbose"] = "verbose"] = "Verbose";
    /** Catastrophic failure, likely abending the process.  */
    Channel[Channel["Fatal"] = "fatal"] = "Fatal";
    /** Hint messages offer guidance or support without forcing action. */
    Channel[Channel["Hint"] = "hint"] = "Hint";
    /** File represents a file output from an extension. Details are a Artifact and are required.  */
    Channel[Channel["File"] = "file"] = "File";
    /** content represents an update/creation of a configuration file. The final uri will be in the same folder as the primary config file. */
    Channel[Channel["Configuration"] = "configuration"] = "Configuration";
})(Channel = exports.Channel || (exports.Channel = {}));
var DocumentType;
(function (DocumentType) {
    DocumentType[DocumentType["OpenAPI2"] = "OpenAPI2"] = "OpenAPI2";
    DocumentType[DocumentType["OpenAPI3"] = "OpenAPI3"] = "OpenAPI3";
    DocumentType[DocumentType["LiterateConfiguration"] = "LiterateConfiguration"] = "LiterateConfiguration";
    DocumentType[DocumentType["Unknown"] = "Unknown"] = "Unknown";
})(DocumentType = exports.DocumentType || (exports.DocumentType = {}));
let resolve_autorest;
let reject_autorest;
exports.AutoRest = new Promise((r, j) => {
    resolve_autorest = r;
    reject_autorest = j;
});
let coreModule = undefined;
let busy = false;
let modulePath = undefined;
/**
 * Returns the language service entrypoint for autorest-core, bootstrapping the core if necessary
 *
 * If initialize has already been called, then it returns the version that was initialized, regardless of parameters
 *
 * @param requestedVersion an npm package reference for the version requested @see {@link https://docs.npmjs.com/cli/install#description}
 *
 * @param minimumVersion - a semver string representing the lowest autorest- core version that is considered acceptable.
 *
 * @see { @link initialize }
 */
async function getLanguageServiceEntrypoint(requestedVersion = "latest-installed", minimumVersion) {
    if (!modulePath && !busy) {
        // if we haven't already got autorest-core, let's do that now with the default settings.
        await initialize(requestedVersion, minimumVersion);
    }
    return autorest_as_a_service_1.resolveEntrypoint(modulePath, "language-service");
}
exports.getLanguageServiceEntrypoint = getLanguageServiceEntrypoint;
/**
 * Returns the command-line application entrypoint for autorest-core, bootstrapping the core if necessary
 *
 * If initialize has already been called, then it returns the version that was initialized, regardless of parameters
 *
 * @param requestedVersion an npm package reference for the version requested @see {@link https://docs.npmjs.com/cli/install#description}
 *
 * @param minimumVersion - a semver string representing the lowest autorest-core version that is considered acceptable.
 *
 * @see {@link initialize}
 * */
async function getApplicationEntrypoint(requestedVersion = "latest-installed", minimumVersion) {
    if (!modulePath && !busy) {
        // if we haven't already got autorest-core, let's do that now with the default settings.
        await initialize(requestedVersion, minimumVersion);
    }
    return autorest_as_a_service_1.resolveEntrypoint(modulePath, "app");
}
exports.getApplicationEntrypoint = getApplicationEntrypoint;
/**
 * Initializes the AutoRest-core module, bootstrapping the core from npm if required.
 *
 * @param requestedVersion an npm package reference for the version requested @see {@link https://docs.npmjs.com/cli/install#description}
 *
 * a) a folder containing a program described by a package.json file
 * b) a gzipped tarball containing (a)
 * c) a url that resolves to (b)
 * d) a <name>@<version> that is published on the registry {@link https://docs.npmjs.com/misc/registry}) with (c)
 * e) a <name>@<tag> (see npm-dist-tag) that points to (d)
 * f) a <name> that has a "latest" tag satisfying (e)
 * g) a <git remote url> that resolves to (a)
 *
 * @param minimumVersion - a semver string representing the lowest autorest-core version that is considered acceptable.
 */
async function initialize(requestedVersion = "latest-installed", minimumVersion) {
    if (modulePath) {
        return;
    }
    if (busy) {
        throw new Error("initialize is already in progress.");
    }
    busy = true;
    try {
        await autorest_as_a_service_1.ensureAutorestHome();
        try {
            // did they pass in a path first?
            const localVersion = path_1.resolve(requestedVersion);
            // try to use a specified folder
            modulePath = await autorest_as_a_service_1.resolveEntrypoint(localVersion, "module");
            if (modulePath) {
                return;
            }
        }
        catch (E) {
            // no local version
        }
        // logic to resolve and optionally install a autorest core package.
        // will throw if it's not doable.
        let selectedVersion = await autorest_as_a_service_1.selectVersion(requestedVersion, false, minimumVersion);
        modulePath = await autorest_as_a_service_1.resolveEntrypoint(await selectedVersion.modulePath, "module");
        if (!modulePath) {
            reject_autorest(new Error(`Unable to start AutoRest Core from ${requestedVersion}/${await selectedVersion.modulePath}`));
            throw new Error(`Unable to start AutoRest Core from ${requestedVersion}/${await selectedVersion.modulePath}`);
        }
    }
    finally {
        busy = false;
    }
}
exports.initialize = initialize;
/** Bootstraps the core module if it's not already done and returns the AutoRest class. */
async function ensureCoreLoaded() {
    if (!modulePath && !busy) {
        // if we haven't already got autorest-core, let's do that now with the default settings.
        await initialize();
    }
    if (modulePath && !coreModule) {
        // get the library entrypoint
        coreModule = await autorest_as_a_service_1.tryRequire(modulePath, "main");
        // assign the type to the Async Class Identity
        resolve_autorest(coreModule.AutoRest);
    }
    // wait for class definition
    return (await exports.AutoRest);
}
/**
 * Creates an instance of the AutoRest engine. Will call {@link initialize} with default values to bootstrap AutoRest core if necessary.
 *
 * @param fileSystem - the {@link IFileSystem} implementation that will be used to acquire files
 *
 * Note: http:/https:/mem: schemes are handled internally in AutoRest and the IFilesystem will not call
 * the IFileSystem methods.
 *
 *
 * @param configFileOrFolderUri - a URI pointing to the folder or autorest configuration file
 */
async function create(fileSystem, configFileOrFolderUri) {
    if (!modulePath && !busy) {
        // if we haven't already got autorest-core, let's do that now with the default settings.
        await initialize();
    }
    if (modulePath && !coreModule) {
        // get the library entrypoint
        coreModule = await autorest_as_a_service_1.tryRequire(modulePath, "main");
        // assign the type to the Async Class Identity
        resolve_autorest(coreModule.AutoRest);
    }
    // wait for class definition
    const CAutoRest = (await exports.AutoRest);
    // return new instance of the AutoRest interface.
    return new CAutoRest(fileSystem, configFileOrFolderUri);
}
exports.create = create;
/**
  *  Given a document's content, does this represent a openapi document of some sort?
  *
  * @param content - the document content to evaluate
  */
async function isOpenApiDocument(content) {
    await ensureCoreLoaded();
    return coreModule.IsOpenApiDocument(content);
}
exports.isOpenApiDocument = isOpenApiDocument;
/**
 * Checks to see if the document is a literate configuation document.
 *
 * @param content the document content to check
 */
async function isConfigurationDocument(content) {
    await ensureCoreLoaded();
    return coreModule.IsConfigurationDocument(content);
}
exports.isConfigurationDocument = isConfigurationDocument;
/** Determines the document type based on the content of the document
 *
 * @returns Promise<DocumentType> one of:
 *  -  DocumentType.LiterateConfiguration - contains the magic string '\n> see https://aka.ms/autorest'
 *  -  DocumentType.OpenAPI2 - $.swagger === "2.0"
 *  -  DocumentType.OpenAPI3 - $.openapi === "3.0.0"
 *  -  DocumentType.Unknown - content does not match a known document type
 *
 * @see {@link DocumentType}
 */
async function identifyDocument(content) {
    await ensureCoreLoaded();
    return await coreModule.IdentifyDocument(content);
}
exports.identifyDocument = identifyDocument;
/**
 * Processes a document (yaml, markdown or JSON) and returns the document as a JSON-encoded document text
 * @param content - the document content
 *
 * @returns the content as a JSON string (not a JSON DOM)
 */
async function toJSON(content) {
    await ensureCoreLoaded();
    return await coreModule.LiterateToJson(content);
}
exports.toJSON = toJSON;
/** This is a convenience class for accessing the requests supported by AutoRest when used as a language service */
class AutoRestLanguageService {
    /**
     * Represents a convenience layer on the remote language service functions (on top of LSP-defined functions)
     *
     * @constructor
     *
     * this requires a reference to the language client so that the methods can await the onReady signal
     * before attempting to send requests.
     */
    constructor(languageClient) {
        this.languageClient = languageClient;
    }
    /**
     * Runs autorest to process a file
     *
     * @param documentUri The OpenApi document or AutoRest configuration file to use for the generation
     *
     * @param language The language to generate code for. (This is a convenience; it could have been expressed in the configuration)
     *
     * @param configuration Additional configuration to pass to AutoRest -- this overrides any defaults or content in the configuration file
     * @returns async: a 'generated' object containg the output from the generation run.
     *    @see generated
     *
     */
    async generate(documentUri, language, configuration) {
        // don't call before the client is ready.
        await this.languageClient.onReady();
        return await this.languageClient.sendRequest("generate", { documentUri: documentUri, language: language, configuration: configuration });
    }
    /**
     * Determines if a file is an OpenAPI document (2.0)
     *
     * @param contentOrUri either a URL to a file on disk or http/s, or the content of a file itself.
     * @returns async:
     *     true - the file is an OpenAPI 2.0 document
     *     false - the file was not recognized.
     */
    async isOpenApiDocument(contentOrUri) {
        // don't call before the client is ready.
        await this.languageClient.onReady();
        return await this.languageClient.sendRequest("isOpenApiDocument", { contentOrUri: contentOrUri });
    }
    /**
     * Determines if a file is an AutoRest configuration file (checks for the magic string `\n> see https://aka.ms/autorest` )
     *
     * @param contentOrUri either a URL to a file on disk or http/s, or the content of a file itself.
     * @returns async:
     *     true - the file is an autorest configuration file
     *     false - the file was not recognized.
     */
    async isConfigurationDocument(contentOrUri) {
        // don't call before the client is ready.
        await this.languageClient.onReady();
        return await this.languageClient.sendRequest("isConfigurationDocument", { contentOrUri: contentOrUri });
    }
    /**
    * Returns the file as a JSON string. This can be a .YAML, .MD or .JSON file to begin with.
    *
    * @param contentOrUri either a URL to a file on disk or http/s, or the content of a file itself.
    * @returns async: string containing the file as JSON
    */
    async toJSON(contentOrUri) {
        // don't call before the client is ready.
        await this.languageClient.onReady();
        return await this.languageClient.sendRequest("toJSON", { contentOrUri: contentOrUri });
    }
    /**
    * Finds the configuration file for a given document URI.
    *
    * @param documentUri the URL to a file on disk or http/s.  The passed in file can be an OpenAPI file or an AutoRest configuration file.
    * @returns async: the URI to the configuration file or an empty string if no configuration could be found.
    *
    */
    async detectConfigurationFile(documentUri) {
        // don't call before the client is ready.
        await this.languageClient.onReady();
        return await this.languageClient.sendRequest("detectConfigurationFile", { documentUri: documentUri });
    }
    /**
    * Determines if a file is an OpenAPI document or a configuration file in one attempt.
    *
    * @param contentOrUri either a URL to a file on disk or http/s, or the content of a file itself.
    * @returns async:
    *     true - the file is a configuration file or OpenAPI (2.0) file
    *     false - the file was not recognized.
    */
    async isSupportedDocument(languageId, contentOrUri) {
        // don't call before the client is ready.
        await this.languageClient.onReady();
        return await this.languageClient.sendRequest("isSupportedDocument", { languageId: languageId, contentOrUri: contentOrUri });
    }
    async identifyDocument(contentOrUri) {
        // don't call before the client is ready.
        await this.languageClient.onReady();
        return await this.languageClient.sendRequest("identifyDocument", { contentOrUri: contentOrUri });
    }
}
exports.AutoRestLanguageService = AutoRestLanguageService;
//# sourceMappingURL=exports.js.map