import { AwaitingInputClosedError, NonInteractiveInputError, } from '../../../../modules/setup-wizard/entities/promptInputError/promptInputError.js';
import { confirmAnswerGuard, choiceAnswerGuard, multiSelectAnswerGuard, } from '../../../../modules/setup-wizard/entities/answerLine/answerLine.guard.js';
function accept(value) {
    return { accepted: true, value };
}
function refuse(refusal) {
    return { accepted: false, refusal };
}
function parseJson(line) {
    try {
        return accept(JSON.parse(line));
    }
    catch {
        return refuse('Réponse illisible');
    }
}
export class PromptStdinJsonGateway {
    dependencies;
    constructor(dependencies) {
        this.dependencies = dependencies;
    }
    async askText(prompt, defaultValue) {
        const line = await this.requestLine({
            prompt,
            kind: 'text',
            options: [],
            defaultValue: defaultValue ?? null,
        });
        if (line.length === 0)
            return defaultValue ?? '';
        return line;
    }
    async askConfirm(prompt) {
        return this.requestValidated({ prompt, kind: 'confirm', options: [], defaultValue: null }, (line) => {
            const parsed = parseJson(line);
            if (!parsed.accepted)
                return parsed;
            if (!confirmAnswerGuard.isValid(parsed.value))
                return refuse('Réponse invalide');
            return accept(parsed.value);
        });
    }
    async askChoice(prompt, choices) {
        const offered = choices.map((choice) => choice.value);
        return this.requestValidated({ prompt, kind: 'choice', options: choices, defaultValue: null }, (line) => {
            const parsed = parseJson(line);
            if (!parsed.accepted)
                return parsed;
            if (!choiceAnswerGuard.isValid(parsed.value))
                return refuse('Réponse invalide');
            if (!offered.includes(parsed.value)) {
                return refuse('Choix invalide, sélectionnez une option proposée');
            }
            return accept(parsed.value);
        });
    }
    async askMultiSelect(prompt, choices) {
        const offered = choices.map((choice) => choice.value);
        return this.requestValidated({ prompt, kind: 'multiSelect', options: choices, defaultValue: null }, (line) => {
            const parsed = parseJson(line);
            if (!parsed.accepted)
                return parsed;
            if (!multiSelectAnswerGuard.isValid(parsed.value))
                return refuse('Réponse invalide');
            if (!parsed.value.every((value) => offered.includes(value))) {
                return refuse("Sélection invalide, une valeur n'est pas proposée");
            }
            return accept(parsed.value);
        });
    }
    guardInteractive() {
        if (this.dependencies.isNonInteractive()) {
            throw new NonInteractiveInputError();
        }
    }
    async requestLine(descriptor) {
        this.guardInteractive();
        this.dependencies.emitter.emitAwaitingInput(this.dependencies.currentStepId(), descriptor.prompt, descriptor.kind, descriptor.options, descriptor.defaultValue);
        const line = await this.dependencies.lineReader.read();
        if (line === null)
            throw new AwaitingInputClosedError();
        return line;
    }
    async requestValidated(descriptor, validate) {
        for (;;) {
            const line = await this.requestLine(descriptor);
            const validation = validate(line);
            if (validation.accepted)
                return validation.value;
            this.dependencies.emitter.emitWarning(validation.refusal);
        }
    }
}
//# sourceMappingURL=prompt.stdinJson.gateway.js.map