"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SpeechRecorder = exports.grammarsFrom = exports.JSGFStrFrom = void 0;
const EventEmitter_1 = require("../../EventEmitter");
const APINotImplementedError_1 = require("../../exception/APINotImplementedError");
const callAll_1 = require("../../util/call/callAll");
const JSGFStrFrom = (tokens) => {
    const rule = tokens.join(' | ');
    const grammar = `#JSGF V1.0; grammar tokens; public <token> = ${rule} ;`;
    return grammar;
};
exports.JSGFStrFrom = JSGFStrFrom;
const grammarsFrom = (system, tokens) => {
    const { api: { speech: { SpeechGrammarList }, }, } = system;
    if (!SpeechGrammarList) {
        throw new APINotImplementedError_1.APINotSupportedError('Speech Grammar List');
    }
    const grammarsStr = (0, exports.JSGFStrFrom)(tokens);
    const grammars = SpeechGrammarList({});
    grammars.addFromString(grammarsStr, 1);
    return grammars;
};
exports.grammarsFrom = grammarsFrom;
class SpeechRecorder extends EventEmitter_1.EventEmitter_ {
    constructor(__system, opt) {
        super();
        this._recording = false;
        const { api: { speech: { SpeechGrammarList, SpeechRecognition }, }, } = __system;
        if (SpeechRecognition && SpeechGrammarList) {
            const { grammars, lang = 'en-US', continuous = false, interimResults = false, maxAlternatives = 1, } = opt;
            let recognition;
            try {
                recognition = SpeechRecognition({
                    grammars: undefined,
                    lang,
                    interimResults,
                    maxAlternatives,
                    continuous,
                });
            }
            catch (err) {
                //
                throw err;
            }
            this._unlisten = (0, callAll_1.callAll)([
                recognition.addListener('error', (error) => {
                    if (error === 'no-speech') {
                        return;
                    }
                }),
                recognition.addListener('end', () => {
                    if (this._recording) {
                        recognition.start();
                    }
                    else {
                        this.emit('end');
                    }
                }),
                recognition.addListener('result', (results) => {
                    const firstResult = results[0];
                    const firstAlternative = firstResult[0];
                    const { transcript, confidence } = firstAlternative;
                    this.emit('transcript', transcript);
                }),
            ]);
            this._recognition = recognition;
        }
    }
    start() {
        if (this._recognition) {
            if (!this._recording) {
                this._recording = true;
                this._recognition.start();
            }
        }
    }
    stop() {
        if (this._recognition) {
            if (this._recording) {
                this._recording = false;
                // stop provides faster recognition (than abort), but it can
                // throw an exception if it is called twice in a row - swallow it
                try {
                    this._recognition.stop();
                }
                catch (_a) { }
                // this._recognition.abort()
            }
        }
    }
}
exports.SpeechRecorder = SpeechRecorder;
//# sourceMappingURL=index.js.map