// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    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) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { MessageType, TranslationStatus, } from "../common/Exports";
import { CancellationErrorCode, CancellationReason, PropertyCollection, PropertyId, ResultReason, TranslationRecognitionCanceledEventArgs, TranslationRecognitionEventArgs, TranslationRecognitionResult, Translations, TranslationSynthesisEventArgs, TranslationSynthesisResult, } from "../sdk/Exports";
import { CancellationErrorCodePropertyName, ConversationServiceRecognizer, EnumTranslation, RecognitionStatus, SynthesisStatus, TranslationHypothesis, TranslationPhrase, TranslationSynthesisEnd, } from "./Exports";
// eslint-disable-next-line max-classes-per-file
export class TranslationServiceRecognizer extends ConversationServiceRecognizer {
    constructor(authentication, connectionFactory, audioSource, recognizerConfig, translationRecognizer) {
        super(authentication, connectionFactory, audioSource, recognizerConfig, translationRecognizer);
        this.privTranslationRecognizer = translationRecognizer;
        this.connectionEvents.attach((connectionEvent) => {
            if (connectionEvent.name === "ConnectionEstablishedEvent") {
                this.privTranslationRecognizer.onConnection();
            }
            else if (connectionEvent.name === "ConnectionClosedEvent") {
                void this.privTranslationRecognizer.onDisconnection();
            }
        });
    }
    processTypeSpecificMessages(connectionMessage) {
        return __awaiter(this, void 0, void 0, function* () {
            const resultProps = new PropertyCollection();
            let processed = yield this.processSpeechMessages(connectionMessage);
            if (processed) {
                return true;
            }
            const handleTranslationPhrase = (translatedPhrase) => __awaiter(this, void 0, void 0, function* () {
                this.privRequestSession.onPhraseRecognized(this.privRequestSession.currentTurnAudioOffset + translatedPhrase.Offset + translatedPhrase.Duration);
                if (translatedPhrase.RecognitionStatus === RecognitionStatus.Success) {
                    // OK, the recognition was successful. How'd the translation do?
                    const result = this.fireEventForResult(translatedPhrase, resultProps);
                    if (!!this.privTranslationRecognizer.recognized) {
                        try {
                            this.privTranslationRecognizer.recognized(this.privTranslationRecognizer, result);
                            /* eslint-disable no-empty */
                        }
                        catch (error) {
                            // Not going to let errors in the event handler
                            // trip things up.
                        }
                    }
                    // report result to promise.
                    if (!!this.privSuccessCallback) {
                        try {
                            this.privSuccessCallback(result.result);
                        }
                        catch (e) {
                            if (!!this.privErrorCallback) {
                                this.privErrorCallback(e);
                            }
                        }
                        // Only invoke the call back once.
                        // and if it's successful don't invoke the
                        // error after that.
                        this.privSuccessCallback = undefined;
                        this.privErrorCallback = undefined;
                    }
                }
                else {
                    const reason = EnumTranslation.implTranslateRecognitionResult(translatedPhrase.RecognitionStatus);
                    const result = new TranslationRecognitionResult(undefined, this.privRequestSession.requestId, reason, translatedPhrase.Text, translatedPhrase.Duration, this.privRequestSession.currentTurnAudioOffset + translatedPhrase.Offset, undefined, connectionMessage.textBody, resultProps);
                    if (reason === ResultReason.Canceled) {
                        const cancelReason = EnumTranslation.implTranslateCancelResult(translatedPhrase.RecognitionStatus);
                        const cancellationErrorCode = EnumTranslation.implTranslateCancelErrorCode(translatedPhrase.RecognitionStatus);
                        yield this.cancelRecognitionLocal(cancelReason, cancellationErrorCode, EnumTranslation.implTranslateErrorDetails(cancellationErrorCode));
                    }
                    else {
                        if (!(this.privRequestSession.isSpeechEnded && reason === ResultReason.NoMatch && translatedPhrase.RecognitionStatus !== RecognitionStatus.InitialSilenceTimeout)) {
                            const ev = new TranslationRecognitionEventArgs(result, result.offset, this.privRequestSession.sessionId);
                            if (!!this.privTranslationRecognizer.recognized) {
                                try {
                                    this.privTranslationRecognizer.recognized(this.privTranslationRecognizer, ev);
                                    /* eslint-disable no-empty */
                                }
                                catch (error) {
                                    // Not going to let errors in the event handler
                                    // trip things up.
                                }
                            }
                        }
                        // report result to promise.
                        if (!!this.privSuccessCallback) {
                            try {
                                this.privSuccessCallback(result);
                            }
                            catch (e) {
                                if (!!this.privErrorCallback) {
                                    this.privErrorCallback(e);
                                }
                            }
                            // Only invoke the call back once.
                            // and if it's successful don't invoke the
                            // error after that.
                            this.privSuccessCallback = undefined;
                            this.privErrorCallback = undefined;
                        }
                    }
                    processed = true;
                }
            });
            if (connectionMessage.messageType === MessageType.Text) {
                resultProps.setProperty(PropertyId.SpeechServiceResponse_JsonResult, connectionMessage.textBody);
            }
            switch (connectionMessage.path.toLowerCase()) {
                case "translation.hypothesis":
                    const result = this.fireEventForResult(TranslationHypothesis.fromJSON(connectionMessage.textBody), resultProps);
                    this.privRequestSession.onHypothesis(this.privRequestSession.currentTurnAudioOffset + result.offset);
                    if (!!this.privTranslationRecognizer.recognizing) {
                        try {
                            this.privTranslationRecognizer.recognizing(this.privTranslationRecognizer, result);
                            /* eslint-disable no-empty */
                        }
                        catch (error) {
                            // Not going to let errors in the event handler
                            // trip things up.
                        }
                    }
                    processed = true;
                    break;
                case "translation.response":
                    const phrase = JSON.parse(connectionMessage.textBody);
                    if (!!phrase.SpeechPhrase) {
                        yield handleTranslationPhrase(TranslationPhrase.fromTranslationResponse(phrase));
                    }
                    break;
                case "translation.phrase":
                    yield handleTranslationPhrase(TranslationPhrase.fromJSON(connectionMessage.textBody));
                    break;
                case "translation.synthesis":
                    this.sendSynthesisAudio(connectionMessage.binaryBody, this.privRequestSession.sessionId);
                    processed = true;
                    break;
                case "translation.synthesis.end":
                    const synthEnd = TranslationSynthesisEnd.fromJSON(connectionMessage.textBody);
                    switch (synthEnd.SynthesisStatus) {
                        case SynthesisStatus.Error:
                            if (!!this.privTranslationRecognizer.synthesizing) {
                                const result = new TranslationSynthesisResult(ResultReason.Canceled, undefined);
                                const retEvent = new TranslationSynthesisEventArgs(result, this.privRequestSession.sessionId);
                                try {
                                    this.privTranslationRecognizer.synthesizing(this.privTranslationRecognizer, retEvent);
                                    /* eslint-disable no-empty */
                                }
                                catch (error) {
                                    // Not going to let errors in the event handler
                                    // trip things up.
                                }
                            }
                            if (!!this.privTranslationRecognizer.canceled) {
                                // And raise a canceled event to send the rich(er) error message back.
                                const canceledResult = new TranslationRecognitionCanceledEventArgs(this.privRequestSession.sessionId, CancellationReason.Error, synthEnd.FailureReason, CancellationErrorCode.ServiceError, null);
                                try {
                                    this.privTranslationRecognizer.canceled(this.privTranslationRecognizer, canceledResult);
                                    /* eslint-disable no-empty */
                                }
                                catch (error) {
                                    // Not going to let errors in the event handler
                                    // trip things up.
                                }
                            }
                            break;
                        case SynthesisStatus.Success:
                            this.sendSynthesisAudio(undefined, this.privRequestSession.sessionId);
                            break;
                        default:
                            break;
                    }
                    processed = true;
                    break;
                default:
                    break;
            }
            return processed;
        });
    }
    // Cancels recognition.
    cancelRecognition(sessionId, requestId, cancellationReason, errorCode, error) {
        const properties = new PropertyCollection();
        properties.setProperty(CancellationErrorCodePropertyName, CancellationErrorCode[errorCode]);
        if (!!this.privTranslationRecognizer.canceled) {
            const cancelEvent = new TranslationRecognitionCanceledEventArgs(sessionId, cancellationReason, error, errorCode, undefined);
            try {
                this.privTranslationRecognizer.canceled(this.privTranslationRecognizer, cancelEvent);
                /* eslint-disable no-empty */
            }
            catch (_a) { }
        }
        if (!!this.privSuccessCallback) {
            const result = new TranslationRecognitionResult(undefined, // Translations
            requestId, ResultReason.Canceled, undefined, // Text
            undefined, // Druation
            undefined, // Offset
            error, undefined, // Json
            properties);
            try {
                this.privSuccessCallback(result);
                /* eslint-disable no-empty */
                this.privSuccessCallback = undefined;
            }
            catch (_b) { }
        }
    }
    handleRecognizingCallback(result, duration, sessionId) {
        try {
            const ev = new TranslationRecognitionEventArgs(TranslationRecognitionResult.fromSpeechRecognitionResult(result), duration, sessionId);
            this.privTranslationRecognizer.recognizing(this.privTranslationRecognizer, ev);
            /* eslint-disable no-empty */
        }
        catch (error) {
            // Not going to let errors in the event handler
            // trip things up.
        }
    }
    handleRecognizedCallback(result, offset, sessionId) {
        try {
            const ev = new TranslationRecognitionEventArgs(TranslationRecognitionResult.fromSpeechRecognitionResult(result), offset, sessionId);
            this.privTranslationRecognizer.recognized(this.privTranslationRecognizer, ev);
        }
        catch (error) {
            // Not going to let errors in the event handler
            // trip things up.
        }
    }
    fireEventForResult(serviceResult, properties) {
        let translations;
        if (undefined !== serviceResult.Translation.Translations) {
            translations = new Translations();
            for (const translation of serviceResult.Translation.Translations) {
                translations.set(translation.Language, translation.Text || translation.DisplayText);
            }
        }
        let resultReason;
        if (serviceResult instanceof TranslationPhrase) {
            if (!!serviceResult.Translation && serviceResult.Translation.TranslationStatus === TranslationStatus.Success) {
                resultReason = ResultReason.TranslatedSpeech;
            }
            else {
                resultReason = ResultReason.RecognizedSpeech;
            }
        }
        else {
            resultReason = ResultReason.TranslatingSpeech;
        }
        const offset = serviceResult.Offset + this.privRequestSession.currentTurnAudioOffset;
        const result = new TranslationRecognitionResult(translations, this.privRequestSession.requestId, resultReason, serviceResult.Text, serviceResult.Duration, offset, serviceResult.Translation.FailureReason, JSON.stringify(serviceResult), properties);
        const ev = new TranslationRecognitionEventArgs(result, offset, this.privRequestSession.sessionId);
        return ev;
    }
    sendSynthesisAudio(audio, sessionId) {
        const reason = (undefined === audio) ? ResultReason.SynthesizingAudioCompleted : ResultReason.SynthesizingAudio;
        const result = new TranslationSynthesisResult(reason, audio);
        const retEvent = new TranslationSynthesisEventArgs(result, sessionId);
        if (!!this.privTranslationRecognizer.synthesizing) {
            try {
                this.privTranslationRecognizer.synthesizing(this.privTranslationRecognizer, retEvent);
                /* eslint-disable no-empty */
            }
            catch (error) {
                // Not going to let errors in the event handler
                // trip things up.
            }
        }
    }
}

//# sourceMappingURL=TranslationServiceRecognizer.js.map
