"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BuildConfigurator = void 0;
const tslib_1 = require("tslib");
const _ = require("lodash");
const contracts_1 = require("@codiac.io/codiac-common/contracts");
const ops_1 = require("../ops");
const ops_2 = require("../ops");
/** Acquires the build command sequence and output folder,
 *  and writes them to the codiac.json as needed.
 */
class BuildConfigurator {
    constructor(_ops, _projCfg, ui, _projectRoot, _cfgRepo, logger) {
        this._ops = _ops;
        this._projCfg = _projCfg;
        this.ui = ui;
        this._projectRoot = _projectRoot;
        this._cfgRepo = _cfgRepo;
        this.logger = logger;
    }
    /**
     * @param given (Optional) Build definition to use.  Governs.
     * @param overwriteDefault Overwrites the default build command for the project with the given buildDef
     */
    getBuildDef(given, overwriteDefault = false) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                try {
                    this.logger.trace(`Given buildDef: [${given || ""}]`);
                    // Get the build command and output folder
                    let ultimate;
                    let outputFolder = /* cfg.outputFolder || */ ops_1.DxConstants.DEFAULT_BUILD_OUTPUT_DIR; // how do we make this accurate?  Hopefully we dont have to make them declare this in the codiac.json...
                    if (given && given.length > 0) {
                        ultimate = given;
                    }
                    else if (this._projCfg.buildDef && this._projCfg.buildDef.length > 0) {
                        ultimate = this._projCfg.buildDef;
                    }
                    if (!ultimate) {
                        // throw new CodiacError(`No build command has been declared for this project in ${ProjectConfig.FILENAME} (set the "buildDef" property to an array of command strings).`);
                        this.ui.userMessage("No build script defined yet.");
                        // Detect some suggestions
                        let defaultCmd;
                        let suggested = [];
                        let tsconfig = this._ops.readTsConfig();
                        if (tsconfig) {
                            defaultCmd = "tsc";
                            suggested.push("tsc");
                            // outputFolder = this.getTsOutputFolder(this._projectRoot, tsconfig);
                        }
                        let pj = yield this._ops.readNpmPackageJson();
                        if (pj && pj.scripts) {
                            let scripts = _.keys(pj.scripts).filter(k => /.*build.*/.test(k));
                            if (scripts.length > 0) {
                                suggested.push(...scripts.map(k => `npm run ${k}`));
                            }
                            if (scripts.find(k => "build"))
                                defaultCmd = "npm run build";
                        }
                        let customChoice = "(enter manually)";
                        if (suggested.length > 1)
                            suggested.unshift(customChoice);
                        // Detect npm and add any scripts named *build* as suggestions (and ask to set "npm run [script-name]", or the content of the script).
                        // Detect typescript and add "tsc" as an option (if its not already)
                        yield this.ui.userMessage("Enter a default command to use for builds:");
                        yield this.ui.userMessage("(pipe '|' delimited statements)");
                        while (!ultimate) {
                            let input;
                            if (suggested.length > 1) {
                                input = yield this.ui.promptSelect("cmds", "Command(s)", suggested);
                                if (input == customChoice) {
                                    input = yield this.ui.prompt("cmd", "Command(s)", true);
                                }
                            }
                            else {
                                input = yield this.ui.prompt("cmd", "Command(s)", true, defaultCmd);
                            }
                            if (!input || input == "") {
                                throw new contracts_1.CodiacError(`No build command has been declared for this project in ${ops_2.OpsConstants.PROJECT_CONFIG_FILENAME} (set the "buildDef" property to an array of command strings, or use the --buildDef command argmment).`);
                            }
                            else {
                                if (input.includes("|")) {
                                    ultimate = input.split("|");
                                }
                                else {
                                    ultimate = [input];
                                }
                                if (ultimate.find(c => /^\s*cod build/.test(c))) {
                                    yield this.ui.userMessage("INVALID COMMAND: The command you provided contains a circular reference to the codiac build command itself.");
                                    ultimate = undefined;
                                }
                            }
                        }
                    }
                    // Save to the project config
                    if (!this._projCfg.buildDef || this._projCfg.buildDef.length == 0 || overwriteDefault == true) {
                        this._projCfg.buildDef = ultimate;
                        this._cfgRepo.updateProjectConfigFile(this._projCfg);
                        this.logger.detail(`New default project build definition saved to project config.`);
                    }
                    resolve(ultimate);
                }
                catch (err) {
                    reject(err);
                }
            }));
        });
    }
}
exports.BuildConfigurator = BuildConfigurator;
//# sourceMappingURL=build-configurator.js.map