"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const readline = require("readline");
/**
 * Writer is a super simple wrapper around the console/standard output for
 * use/replacement in testing.
 */
class Writer {
    constructor() {
        this.fn = console.log.bind(console);
        this.readline = readline.createInterface(process.stdin, process.stdout);
    }
    /**
     * Writes a message out to the console.
     */
    write(...message) {
        this.fn(...message);
    }
    /**
     * writeWrapped prints the message and wraps it at a certain character width.
     */
    writeWrapped(message, width = 79) {
        while (message.length > 0) {
            let end = width;
            if (message.length > end) {
                end = message.slice(0, width).lastIndexOf(' ');
            }
            if (end === -1) {
                end = width;
            }
            this.fn(message.slice(0, end));
            message = message.slice(end).trim();
        }
    }
    /**
     * Prompts the user whether they'd like to continue the current operation.
     * Returns whether they've given consent to continue.
     */
    confirm(question, defaultValue = true) {
        return __awaiter(this, void 0, void 0, function* () {
            this.writeWrapped(question);
            let answer = yield new Promise(resolve => {
                this.readline.question(`\nContinue? ${defaultValue ? '[y]/n' : 'y/[n]'}: `, resolve);
            });
            answer = answer.toLowerCase();
            if (defaultValue) {
                return answer[0] !== 'n';
            }
            return answer[0] === 'y';
        });
    }
    /**
     * Prompts the user with a question, and records their answer as a string.
     * Optionally takes a `validate` function. If the validator returns a string,
     * it will be printed and the user will be prompted to
     * answer the question again.
     */
    ask(question, defaultValue, validate) {
        return __awaiter(this, void 0, void 0, function* () {
            // tslint:disable-next-line
            while (true) {
                let answer = yield new Promise(resolve => {
                    this.readline.question(`${question} ${defaultValue ? `[${defaultValue}] ` : ''}`, resolve);
                });
                answer = answer.trim();
                if (!answer && defaultValue) {
                    answer = defaultValue;
                }
                if (!validate) {
                    return answer;
                }
                const errorMessage = validate(answer);
                if (!errorMessage) {
                    return answer;
                }
                this.writeWrapped(errorMessage);
            }
        });
    }
}
exports.Writer = Writer;
exports.default = new Writer();
