const BaseEngine = require('../BaseEngine');
const sdk = require("microsoft-cognitiveservices-speech-sdk");
const fetch = require('node-fetch');

module.exports = class AzureTTS extends BaseEngine {
    constructor() {
        super("azure", "Microsoft Azure TTS", "wav");
        this.voices = {};
        this.populateVoiceList();
    }

    getDefaultVoice() {
        return "Aria";
    }

    getSpeechFile(text, filepath, voice = this.getDefaultVoice(), params = {}) {
        return new Promise((resolve, reject) => {
            const speechConfig = sdk.SpeechConfig.fromSubscription(process.env.AZURE_API_KEY, process.env.AZURE_REGION);
            speechConfig.speechSynthesisOutputFormat = sdk.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm;
            speechConfig.speechSynthesisVoiceName = this.voices[voice];
            const audioConfig = sdk.AudioConfig.fromAudioFileOutput(filepath);
            const synthesizer = new sdk.SpeechSynthesizer(speechConfig, audioConfig);
            synthesizer.speakTextAsync(
                text,
                result => {
                    synthesizer.close();
                    if (result) {
                        // return result as stream
                        resolve(filepath);
                    }
                },
                error => {
                    console.log(error);
                    synthesizer.close();
                    reject(error);
                });
        })
    }

    async populateVoiceList() {
        const opts = {
            headers: {
                'Ocp-Apim-Subscription-Key': process.env.AZURE_API_KEY
            }
        }
        const res = await fetch(process.env.AZURE_LIST_ENDPOINT, opts);
        const json = await res.json();
        json.forEach((voice) => {
            if (this.voices[voice.DisplayName.toLowerCase()]) {
                if (voice.Name.includes('Neural')) {
                    this.voices[voice.DisplayName.toLowerCase()] = voice.ShortName;
                }
            } else {
                this.voices[voice.DisplayName.toLowerCase()] = voice.ShortName;
            }
        });
    }
}