<template>
    <div class="card">
        <!-- Header containing info and actions for the transcription -->
        <div class="transcription__header">
            <button class="btn-fab" v-on:click="toggleAudio" type="button" :title="translations.get('TranscriptionItem_PlayButtonTooltip')">
                <span class="material-icons mdi-l play-button" v-if="!isPlaying">play_arrow</span>
                <span class="material-icons mdi-l play-button" v-if="isPlaying">pause</span>
            </button>

            <span>{{ translations.get("TranscriptionItem_FileName") }}: {{ transcription.fileName }}</span>

            <div style="position: relative;">
                <button class="btn-primary" @mouseover="showDownloadOptions = true" @mouseout="showDownloadOptions = false" type="button">
                    <span class="material-icons">download</span>
                    <span>{{ translations.get("TranscriptionItem_Download") }}</span>
                </button>

                <div class="download-popup card" :class="{ 'download-popup-show': showDownloadOptions }"
                     @mouseover="showDownloadOptions = true" @mouseout="showDownloadOptions = false">
                    <button @click="downloadAsText" type="button" class="btn-primary theme-flat">
                        <span class="material-icons">text_snippet</span>
                        <span>{{ translations.get("TranscriptionItem_DownloadAsText") }}</span>
                    </button>

                    <button @click="downloadAsJson" type="button" class="btn-primary theme-flat">
                        <span class="material-icons">integration_instructions</span>
                        <span>{{ translations.get("TranscriptionItem_DownloadAsJson") }}</span>
                    </button>

                    <button @click="downloadAsWebvtt" type="button" class="btn-primary theme-flat">
                        <span class="material-icons">subtitles</span>
                        <span>{{ translations.get("TranscriptionItem_DownloadAsWebvtt") }}</span>
                    </button>
                </div>
            </div>

            <button class="btn-primary theme-error" @click="remove" type="button">
                <span class="material-icons">delete</span>
                <span>{{ translations.get("TranscriptionItem_Remove") }}</span>
            </button>
        </div>

        <div class="editor-controls">
            <audio-time-bar v-model.number="currentPlaybackTime" :audio-length="audioLength" :isDisabled="playbackState.id != transcription.id" />
        </div>

        <hr />

        <div class="editor-controls">
            <TranscriptionItemEditor ref="editor" :transcription="transcription" style="margin-bottom: 1em" :enableEditing="enableEditing" />
            <toggle-button v-model="enableEditing" :title="translations.get('TranscriptionItemEditor_ToggleEditTooltip')">
                <span class="material-icons">edit</span>
            </toggle-button>
        </div>
    </div>
</template>

<style scoped lang="scss">
.transcription__header {
    display: grid;
    gap: 0.5em 0.5em;
    grid-template-columns: auto 1fr auto auto;
    align-items: center;
}

.download-popup {
    display: flex;
    flex-direction: column;
    align-items: stretch;

    position: absolute;
    top: 97%;
    z-index: 2;

    padding: 2px;
    margin: 0;
    width: 14em;

    transition-duration: var(--transition-duration);
    visibility: hidden;
    opacity: 0;
}

.download-popup-show {
    visibility: visible;
    opacity: 1;
}

.editor-controls {
    display: grid;
    align-items: flex-start;
    grid-template-columns: 1fr auto;
    margin: 0.5em 0 0.3em 0;
    gap: 1em;
}

.rotate-180 {
    transform: rotate(180deg);
}
</style>

<script>
import { mapState } from "vuex";
import { saveAs } from "file-saver"
import { TranscriptionViewModel } from "../main";
import AudioPlayback from "../js/AudioPlaybackModule"
import Util from "../js/Util"
import AudioTimeBar from "./AudioTimeBar.vue"
import TranscriptionItemEditor from "./TranscriptionItemEditor.vue"

export default {
    name: "TranscriptionItem",
    components: {
        AudioTimeBar,
        TranscriptionItemEditor
    },
    props: {
        transcription: TranscriptionViewModel
    },
    data() {
        return {
            enableEditing: false,
            showDownloadOptions: false
        }
    },
    computed: {
        currentPlaybackTime: {
            get() {
                return this.$store.getters.transcriptionPlaybackTime(this.transcription.id);
            },
            set(value) {
                this.$store.commit("playbackStateSetTime", { id: this.transcription.id, time: value });
            }
        },
        audioLength() {
            return this.$store.getters.transcriptionPlaybackLength(this.transcription.id);
        },
        isPlaying() {
            return this.playbackState.isPlaying && this.playbackState.id === this.transcription.id;
        },
        ...mapState({
            translations: state => state.translations,
            playbackState: state => state.playbackState
        })
    },
    methods: {
        async toggleAudio() {
            this.isPlaying ? AudioPlayback.pause() : await AudioPlayback.play(this.transcription.id, -1);
        },
        remove() {
            this.$store.commit("rawTranscriptionRemove", this.transcription.id);
        },
        downloadAsText() {
            const fileName = buildDownloadableFileName(this.transcription.fileName, "txt");

            const blob = new Blob([ this.$refs.editor.words.map(w => w.word).join(" ") ], { type: "text/plain;charset=utf-8" });
            saveAs(blob, fileName);
        },
        downloadAsJson() {
            const fileName = buildDownloadableFileName(this.transcription.fileName, "json");
            const toDownload = (({ fileName, transcription }) => ({ fileName, transcription }))(this.transcription);
            toDownload.words = this.$refs.editor.words.map(w => (({ word, startTime, endTime }) => ({ word, startTime, endTime }))(w));

            const blob = new Blob([ JSON.stringify(toDownload, null, 4) ], { type: "application/json;charset=utf-8" });
            saveAs(blob, fileName);
        },
        downloadAsWebvtt() {
            const fileName = buildDownloadableFileName(this.transcription.fileName, "vtt");
            const toDownload = buildWebvttFileContents(this.transcription, this.$refs.editor);

            const blob = new Blob([ toDownload ], { type: "text/vtt;charset=utf-8" });
            saveAs(blob, fileName);
        }
    }
}

/**
 * Builds a file name for a download.
 * @param {String} transcriptionFileName The name of the transcription that will be downloaded.
 * @param {String} extension The file extension of the download. Do not include a period.
 * @returns {String} The file name.
 */
function buildDownloadableFileName(transcriptionFileName, extension) {
    const extensionIndex = transcriptionFileName.lastIndexOf(".");
    let fileName = transcriptionFileName.slice(0, extensionIndex);
    fileName += "_transcription." + extension;

    return fileName;
}

/**
 * Builds a WebVTT file of the given transcription
 * @param {TranscriptionViewModel} transcription The transcription.
 * @returns {String} The WebVTT content.
 */
function buildWebvttFileContents(transcription, editor) {
    let contents = "WEBVTT Transcription of " + transcription.fileName + "\n\n";

    for (const word of editor.words) {
        const startTime = Util.formatSecondsTimeString(word.startTime, true);
        const endTime = Util.formatSecondsTimeString(word.endTime, true);

        contents += startTime + " --> " + endTime + "\n";
        contents += "- " + word.word + "\n\n";
    }

    return contents;
}
</script>
