'use strict';

class Transcription {
    constructor() {
        this.languages = [
            ['Afrikaans', ['af-ZA']],
            ['Bahasa Indonesia', ['id-ID']],
            ['Bahasa Melayu', ['ms-MY']],
            ['Català', ['ca-ES']],
            ['Čeština', ['cs-CZ']],
            ['Deutsch', ['de-DE']],
            [
                'English',
                ['en-AU', 'Australia'],
                ['en-CA', 'Canada'],
                ['en-IN', 'India'],
                ['en-NZ', 'New Zealand'],
                ['en-ZA', 'South Africa'],
                ['en-GB', 'United Kingdom'],
                ['en-US', 'United States'],
            ],
            [
                'Español',
                ['es-AR', 'Argentina'],
                ['es-BO', 'Bolivia'],
                ['es-CL', 'Chile'],
                ['es-CO', 'Colombia'],
                ['es-CR', 'Costa Rica'],
                ['es-EC', 'Ecuador'],
                ['es-SV', 'El Salvador'],
                ['es-ES', 'España'],
                ['es-US', 'Estados Unidos'],
                ['es-GT', 'Guatemala'],
                ['es-HN', 'Honduras'],
                ['es-MX', 'México'],
                ['es-NI', 'Nicaragua'],
                ['es-PA', 'Panamá'],
                ['es-PY', 'Paraguay'],
                ['es-PE', 'Perú'],
                ['es-PR', 'Puerto Rico'],
                ['es-DO', 'República Dominicana'],
                ['es-UY', 'Uruguay'],
                ['es-VE', 'Venezuela'],
            ],
            ['Euskara', ['eu-ES']],
            ['Français', ['fr-FR']],
            ['Galego', ['gl-ES']],
            ['Hrvatski', ['hr_HR']],
            ['IsiZulu', ['zu-ZA']],
            ['Íslenska', ['is-IS']],
            ['Italiano', ['it-IT', 'Italia'], ['it-CH', 'Svizzera']],
            ['Magyar', ['hu-HU']],
            ['Nederlands', ['nl-NL']],
            ['Norsk bokmål', ['nb-NO']],
            ['Polski', ['pl-PL']],
            ['Português', ['pt-BR', 'Brasil'], ['pt-PT', 'Portugal']],
            ['Română', ['ro-RO']],
            ['Slovenčina', ['sk-SK']],
            ['Suomi', ['fi-FI']],
            ['Svenska', ['sv-SE']],
            ['Türkçe', ['tr-TR']],
            ['български', ['bg-BG']],
            ['Pусский', ['ru-RU']],
            ['Српски', ['sr-RS']],
            ['한국어', ['ko-KR']],
            [
                '中文',
                ['cmn-Hans-CN', '普通话 (中国大陆)'],
                ['cmn-Hans-HK', '普通话 (香港)'],
                ['cmn-Hant-TW', '中文 (台灣)'],
                ['yue-Hant-HK', '粵語 (香港)'],
            ],
            ['日本語', ['ja-JP']],
            ['Lingua latīna', ['la']],
        ];
        this.speechTranscription = window.SpeechRecognition || window.webkitSpeechRecognition;
        this.isTranscriptionSupported = false;
        this.transcriptionRunning = false;
        this.transcription;
        this.transcripts = [];
        this.isBgTransparent = false;
        this.isPinned = false;
        this.isHidden = true;
        this.isPersistentMode = false;
        this.isPersistent = false;
        this.showOnMessage = true;
    }

    isSupported() {
        return Boolean(this.speechTranscription);
    }

    init() {
        if (this.isSupported()) {
            this.handleLanguages();

            this.transcription = new this.speechTranscription();
            this.transcription.maxAlternatives = 1;
            this.transcription.continuous = true;
            this.transcription.lang = transcriptionDialect.value;

            this.transcription.onstart = function () {
                console.log('Transcription started');
                hide(transcriptionSpeechStart);
                show(transcriptionSpeechStop);
                setColor(transcriptionSpeechStatus, 'lime');
                !transcription.isPersistentMode
                    ? userLog('info', 'Transcription started', 'top-end')
                    : (transcription.isPersistent = true);
            };

            this.transcription.onresult = (e) => {
                const current = e.resultIndex;
                const transcript = e.results[current][0].transcript;
                const transcriptionData = {
                    type: 'transcript',
                    room_id: room_id,
                    peer_name: peer_name,
                    text_data: transcript,
                    time_stamp: new Date(),
                    broadcast: true,
                };
                if (transcript) {
                    this.sendTranscript(transcriptionData);
                    this.handleTranscript(transcriptionData);
                }
            };

            this.transcription.onaudiostart = () => {
                console.log('Transcription start to capture your voice');
            };

            this.transcription.onaudioend = () => {
                console.log('Transcription stop to capture your voice');
            };

            this.transcription.onerror = function (event) {
                console.error('Transcription error', event.error);
                if (!transcription.isPersistent || !transcription.isPersistentMode)
                    userLog('error', `Transcription error ${event.error}`, 'top-end', 6000);
            };

            this.transcription.onend = function () {
                console.log('Transcription stopped');
                hide(transcriptionSpeechStop);
                show(transcriptionSpeechStart);
                setColor(transcriptionSpeechStatus, 'white');
                // Prevent stopping in the absence of speech...
                if (
                    transcription.isPersistentMode &&
                    transcription.isPersistent &&
                    transcription.transcriptionRunning
                ) {
                    setTimeout(() => {
                        transcription.start();
                    }, 2000);
                } else {
                    transcription.isPersistent = false;
                    userLog('info', 'Transcription stopped', 'top-end');
                }
            };

            this.isTranscriptionSupported = true;
            console.info('This Browser support Transcription');
        } else {
            console.warn(
                'This browser not support Transcription, check out supported browsers: https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API#browser_compatibility',
            );
        }
    }

    sendTranscript(transcriptionData) {
        if (rc.thereAreParticipants()) {
            //console.log('TRANSCRIPTION SEND', transcriptionData);
            rc.emitCmd(transcriptionData);
        }
    }

    handleTranscript(transcriptionData) {
        console.log('TRANSCRIPTION TEXT', transcriptionData.text_data);

        transcriptionData.text_data = filterXSS(transcriptionData.text_data);
        transcriptionData.peer_name = filterXSS(transcriptionData.peer_name);

        const { peer_name, text_data } = transcriptionData;
        const time_stamp = rc.getTimeNow();
        const avatar_image = rc.isValidEmail(peer_name) ? rc.genGravatar(peer_name) : rc.genAvatarSvg(peer_name, 32);

        if (this.isHidden) {
            if (this.showOnMessage) {
                this.toggle();
            } else {
                this.handleTranscriptionPopup(transcriptionData);
            }
        }

        const msgHTML = `
        <div class="msg-transcription left-msg-transcription">
            <img class="msg-transcription-img" src="${avatar_image}" />
            <div class="msg-transcription-bubble">
                <div class="msg-transcription-info">
                    <div class="msg-transcription-info-name">${peer_name} : ${time_stamp}</div>
                </div>
                <div class="msg-transcription-text">${text_data}</div>
            </div>
        </div>
        `;
        transcriptionChat.insertAdjacentHTML('beforeend', msgHTML);
        transcriptionChat.scrollTop += 500;

        this.transcripts.push({
            time: time_stamp,
            name: peer_name,
            caption: text_data,
        });
        rc.sound('transcript');
    }

    handleTranscriptionPopup(transcriptionData, duration = 5000) {
        const transcriptionDisplay = document.createElement('div');
        transcriptionDisplay.className = 'animate__animated animate__fadeInUp';
        transcriptionDisplay.style.padding = '10px';
        transcriptionDisplay.style.fontSize = '1rem';
        transcriptionDisplay.style.color = '#FFF';
        transcriptionDisplay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
        transcriptionDisplay.style.borderRadius = '10px';
        transcriptionDisplay.innerText = `${transcriptionData.peer_name}: ${transcriptionData.text_data}`;
        transcriptionPopup.appendChild(transcriptionDisplay);
        setTimeout(() => {
            transcriptionDisplay.remove();
        }, duration);
    }

    toggle() {
        if (this.isHidden) {
            this.center();
            transcriptionRoom.style.display = 'block';
            rc.sound('open');
        } else {
            transcriptionRoom.style.display = 'none';
        }
        this.isHidden = !this.isHidden;
        if (this.isPinned) this.unpinned();
        resizeTranscriptionRoom();
    }

    toggleBg() {
        this.isBgTransparent = !this.isBgTransparent;
        this.isBgTransparent
            ? document.documentElement.style.setProperty('--transcription-bg', 'rgba(0, 0, 0, 0.100)')
            : setTheme();
    }

    maximize() {
        hide(transcriptionMaxBtn);
        show(transcriptionMinBtn);
        this.center();
        document.documentElement.style.setProperty('--transcription-width', '100%');
        document.documentElement.style.setProperty('--transcription-height', '100%');
    }

    minimize() {
        hide(transcriptionMinBtn);
        show(transcriptionMaxBtn);
        if (this.isPinned) {
            this.pinned();
        } else {
            this.center();
            document.documentElement.style.setProperty('--transcription-width', '420px');
            document.documentElement.style.setProperty('--transcription-height', '680px');
        }
    }

    center() {
        transcriptionRoom.style.position = 'fixed';
        transcriptionRoom.style.transform = 'translate(-50%, -50%)';
        transcriptionRoom.style.top = '50%';
        transcriptionRoom.style.left = '50%';
    }

    togglePinUnpin() {
        if (rc.isChatPinned) {
            return userLog('info', 'Please unpin the chat that appears to be currently pinned', 'top-end');
        }
        this.isPinned ? this.unpinned() : this.pinned();
        rc.sound('click');
    }

    isPin() {
        return this.isPinned;
    }

    pinned() {
        if (!rc.isVideoPinned) {
            rc.videoMediaContainer.style.top = 0;
            rc.videoMediaContainer.style.width = '75%';
            rc.videoMediaContainer.style.height = '100%';
        }
        this.pin();
        this.isPinned = true;
        setColor(transcriptionTogglePinBtn, 'lime');
        resizeVideoMedia();
        transcriptionRoom.style.resize = 'none';
        if (!rc.isMobileDevice) rc.makeUnDraggable(transcriptionRoom, transcriptionHeader);
    }

    pin() {
        transcriptionRoom.style.position = 'absolute';
        transcriptionRoom.style.top = 0;
        transcriptionRoom.style.right = 0;
        transcriptionRoom.style.left = null;
        transcriptionRoom.style.transform = null;
        document.documentElement.style.setProperty('--transcription-width', '25%');
        document.documentElement.style.setProperty('--transcription-height', '100%');
    }

    unpinned() {
        if (!rc.isVideoPinned) {
            rc.videoMediaContainer.style.top = 0;
            rc.videoMediaContainer.style.right = null;
            rc.videoMediaContainer.style.width = '100%';
            rc.videoMediaContainer.style.height = '100%';
        }
        document.documentElement.style.setProperty('--transcription-width', '420px');
        document.documentElement.style.setProperty('--transcription-height', '680px');
        hide(transcriptionMinBtn);
        show(transcriptionMaxBtn);
        this.center();
        this.isPinned = false;
        setColor(transcriptionTogglePinBtn, 'white');
        resizeVideoMedia();
        resizeTranscriptionRoom();
        transcriptionRoom.style.resize = 'both';
        if (!rc.isMobileDevice) rc.makeDraggable(transcriptionRoom, transcriptionHeader);
    }

    save() {
        if (this.transcripts.length != 0) {
            const a = document.createElement('a');
            a.href = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(this.transcripts, null, 1));
            a.download = getDataTimeString() + room_id + '-TRANSCRIPTIONS.txt';
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            rc.sound('download');
        } else {
            userLog('info', "There isn't transcriptions to save", 'top-end');
        }
    }

    delete() {
        if (this.transcripts.length != 0) {
            Swal.fire({
                background: swalBackground,
                position: 'center',
                title: 'Clean up all transcripts?',
                imageUrl: image.delete,
                showDenyButton: true,
                confirmButtonText: `Yes`,
                denyButtonText: `No`,
                showClass: { popup: 'animate__animated animate__fadeInDown' },
                hideClass: { popup: 'animate__animated animate__fadeOutUp' },
            }).then((result) => {
                if (result.isConfirmed) {
                    let captions = transcriptionChat.firstChild;
                    while (captions) {
                        transcriptionChat.removeChild(captions);
                        captions = transcriptionChat.firstChild;
                    }
                    this.transcripts = [];
                    rc.sound('delete');
                }
            });
        } else {
            userLog('info', "There isn't transcriptions to delete", 'top-end');
        }
    }

    updateCountry() {
        for (let i = transcriptionDialect.options.length - 1; i >= 0; i--) {
            transcriptionDialect.remove(i);
        }
        let list = this.languages[transcriptionLanguage.selectedIndex];
        for (let i = 1; i < list.length; i++) {
            transcriptionDialect.options.add(new Option(list[i][1], list[i][0]));
        }
        transcriptionDialect.style.visibility = list[1].length == 1 ? 'hidden' : 'visible';
    }

    handleLanguages() {
        for (let i = 0; i < this.languages.length; i++) {
            transcriptionLanguage.options[i] = new Option(this.languages[i][0], i);
        }

        transcriptionLanguage.selectedIndex = 6;
        this.updateCountry();

        transcriptionDialect.selectedIndex = 6;
        transcriptionLanguage.onchange = () => {
            this.updateCountry();
        };
    }

    start() {
        try {
            this.transcriptionRunning = true;
            this.transcription.lang = transcriptionDialect.value;
            this.selectDisabled(true);
            this.transcription.start();
        } catch (error) {
            this.transcriptionRunning = false;
            userLog('error', `Transcription start error ${error.message}`, 'top-end', 6000);
            console.error('Transcription start error', error);
        }
    }

    stop() {
        this.transcriptionRunning = false;
        this.isPersistent = false;
        this.selectDisabled(false);
        this.transcription.stop();
    }

    selectDisabled(disabled = false) {
        transcriptionLanguage.disabled = disabled;
        transcriptionDialect.disabled = disabled;
        transcriptPersistentMode.disabled = disabled;
    }
}
