<template>
    <div class="cw-block cw-block-canvas" ref="block">
        <courseware-default-block
            :block="block"
            :canEdit="canEdit"
            :isTeacher="isTeacher"
            :preview="true"
            @storeEdit="storeBlock"
            @closeEdit="initCurrentData"
        >
            <template #content>
                <div v-if="currentTitle" class="cw-block-title">
                    {{ currentTitle }}
                </div>
                <div class="cw-canvasblock-toolbar">
                    <div class="cw-canvasblock-buttonset">
                        <button class="cw-canvasblock-reset" :title="$gettext('Zurücksetzen')" @click="reset"></button>
                        <button class="cw-canvasblock-undo" :title="$gettext('Rückgängig')" @click="undo"></button>
                        <button v-if="hasUploadFolder" class="cw-canvasblock-store" :title="$gettext('Bild im Dateibereich speichern')" @click="store"></button>
                    </div>
                    <div class="cw-canvasblock-buttonset">
                        <button
                            v-for="(rgba, color) in colors"
                            :key="color"
                            class="cw-canvasblock-color"
                            :class="[currentColor === color ? 'selected-color' : '', color]"
                            @click="setColor(color)"
                        />
                    </div>
                    <div class="cw-canvasblock-buttonset">
                        <button
                            class="cw-canvasblock-size cw-canvasblock-size-small"
                            :class="{ 'selected-size': currentSize === 2 }"
                            :title="$gettext('klein')"
                            @click="setSize('small')"
                        />
                        <button
                            class="cw-canvasblock-size cw-canvasblock-size-normal"
                            :class="{ 'selected-size': currentSize === 5 }"
                            :title="$gettext('normal')"
                            @click="setSize('normal')"
                        />
                        <button
                            class="cw-canvasblock-size cw-canvasblock-size-large"
                            :class="{ 'selected-size': currentSize === 8 }"
                            :title="$gettext('groß')"
                            @click="setSize('large')"
                        />
                        <button
                            class="cw-canvasblock-size cw-canvasblock-size-huge"
                            :class="{ 'selected-size': currentSize === 12 }"
                            :title="$gettext('riesig')"
                            @click="setSize('huge')"
                        />
                    </div>
                    <div class="cw-canvasblock-buttonset">
                        <button
                            class="cw-canvasblock-tool cw-canvasblock-tool-pen"
                            :class="{ 'selected-tool': currentTool === 'pen' }"
                            :title="$gettext('Zeichenwerkzeug')"
                            @click="setTool('pen')"
                        />
                        <button
                            class="cw-canvasblock-tool cw-canvasblock-tool-text"
                            :class="{ 'selected-tool': currentTool === 'text' }"
                            :title="$gettext('Textwerkzeug')"
                            @click="setTool('text')"
                        >
                            T
                        </button>
                    </div>
                </div>
                <img :src="currentUrl" class="cw-canvasblock-original-img" ref="image" @load="buildCanvas" />
                <input
                    v-show="textInput"
                    class="cw-canvasblock-text-input"
                    ref="textInputField"
                    @keyup="textInputKeyUp"
                />
                <canvas
                    class="cw-canvasblock-canvas"
                    :class="{
                        'cw-canvasblock-tool-selected-pen': currentTool === 'pen',
                        'cw-canvasblock-tool-selected-text': currentTool === 'text',
                    }"
                    ref="canvas"
                    @mousedown="mouseDown"
                    @mousemove="mouseMove"
                    @mouseup="mouseUp"
                    @mouseout="mouseUp"
                    @mouseleave="mouseUp"

                    @touchstart="touchStart"
                    @touchmove="touchMove"
                    @touchend="touchEnd"
                />
                <div class="cw-canvasblock-hints">
                    <div v-show="write" class="messagebox messagebox_info cw-canvasblock-text-info">
                        <translate>Texteingabe mit Enter-Taste bestätigen</translate>
                    </div>
                </div>
            </template>
            <template v-if="canEdit" #edit>
                <form class="default" @submit.prevent="">
                    <label>
                        <translate>Überschrift</translate>
                        <input type="text" v-model="currentTitle" />
                    </label>
                    <label>
                        <translate>Hintergrundbild</translate>
                        <select v-model="currentImage">
                            <option value="true"><translate>Ja</translate></option>
                            <option value="false"><translate>Nein</translate></option>
                        </select>
                    </label>
                    <label v-if="currentImage === 'true'">
                        <translate>Bilddatei</translate>
                        <courseware-file-chooser
                            v-model="currentFileId"
                            :isImage="true"
                            @selectFile="updateCurrentFile"
                        />
                    </label>
                    <label>
                        <translate>Speicherort</translate>
                        <courseware-folder-chooser v-model="currentUploadFolderId" :unchoose="true"/>
                    </label>
                    <label>
                        <translate>Werte anderer Nutzer anzeigen</translate>
                        <select v-model="currentShowUserData">
                            <option value="off"><translate>deaktiviert</translate></option>
                            <option value="teacher"><translate>nur für Lehrende</translate></option>
                            <option value="all"><translate>für alle</translate></option>
                        </select>
                    </label>
                </form>
            </template>
            <template #info>
                <p><translate>Informationen zum Leinwand-Block</translate></p>
            </template>
        </courseware-default-block>
    </div>
</template>

<script>
import CoursewareDefaultBlock from './CoursewareDefaultBlock.vue';
import CoursewareFileChooser from './CoursewareFileChooser.vue';
import CoursewareFolderChooser from './CoursewareFolderChooser.vue';

import { mapActions, mapGetters } from 'vuex';

export default {
    name: 'courseware-canvas-block',
    components: {
        CoursewareDefaultBlock,
        CoursewareFileChooser,
        CoursewareFolderChooser,
    },
    props: {
        block: Object,
        canEdit: Boolean,
        isTeacher: Boolean,
    },
    data() {
        return {
            currentTitle: '',
            currentImage: '',
            currentFileId: '',
            currentUploadFolderId: '',
            currentShowUserData: '',
            currentFile: {},

            context: {},
            paint: false,
            write: false,
            clickX: [],
            clickY: [],
            clickDrag: [],
            clickColor: [],
            colors: {
                white: 'rgba(255,255,255,1)',
                blue: 'rgba(52,152,219,1)',
                green: 'rgba(46,204,113,1)',
                purple: 'rgba(155,89,182,1)',
                red: 'rgba(231,76,60,1)',
                yellow: 'rgba(254,211,48,1)',
                orange: 'rgba(243,156,18,1)',
                grey: 'rgba(149,165,166,1)',
                darkgrey: 'rgba(52,73,94,1)',
                black: 'rgba(0,0,0,1)',
            },
            currentColor: '',
            currentColorRGBA: '',
            sizes: { small: 2, normal: 5, large: 8, huge: 12 },
            clickSize: [],
            currentSize: '',
            tools: { pen: 'pen', text: 'text' },
            currentTool: '',
            clickTool: [],
            Text: [],
            textInput: false,
            file: null
        };
    },
    computed: {
        ...mapGetters({
            userId: 'userId',
            getUserDataById: 'courseware-user-data-fields/byId',
            usersById: 'users/byId',
        }),
        userData() {
            return this.getUserDataById({ id: this.block.relationships['user-data-field'].data.id });
        },
        canvasDraw() {
            if (this.userData !== undefined && this.userData.attributes.payload.canvas_draw) {
                return this.userData.attributes.payload.canvas_draw;
            } else {
                return false;
            }
        },
        title() {
            return this.block?.attributes?.payload?.title;
        },
        image() {
            return this.block?.attributes?.payload?.image;
        },
        fileId() {
            return this.block?.attributes?.payload?.file_id;
        },
        uploadFolderId() {
            return this.block?.attributes?.payload?.upload_folder_id;
        },
        showUsersData() {
            return this.block?.attributes?.payload?.show_usersdata;
        },
        currentUrl() {
            if (this.currentFile?.meta) {
                return this.currentFile.meta['download-url'];
            } else if(this.currentFile?.download_url) {
                    return this.currentFile.download_url;
            } else {
                return '';
            }
        },
        currentFileName() {
            if (this.currentFile?.attributes?.name) {
                return this.currentFile.attributes.name;
            } else {
                return this.currentTitle + '.jpg';
            }
        },
        hasUploadFolder() {
            return this.currentUploadFolderId !== "";
        },
    },
    mounted() {
        this.loadFileRefs(this.block.id).then((response) => {
            this.file = response[0];
            this.currentFile = this.file;
            this.initCurrentData();
            this.buildCanvas();
        });
    },
    methods: {
        ...mapActions({
            updateBlock: 'updateBlockInContainer',
            loadFileRefs: 'loadFileRefs',
            createFile: 'createFile',
            companionSuccess: 'companionSuccess',
            companionError: 'companionError',
        }),
        initCurrentData() {
            this.currentTitle = this.title;
            this.currentImage = this.image;
            this.currentFileId = this.fileId;
            this.currentUploadFolderId = this.uploadFolderId;
            this.currentShowUserData = this.showUsersData;
            if (this.canvasDraw) {
                this.clickX = JSON.parse(this.canvasDraw.clickX);
                this.clickY = JSON.parse(this.canvasDraw.clickY);
                this.clickDrag = JSON.parse(this.canvasDraw.clickDrag);
                this.clickColor = JSON.parse(this.canvasDraw.clickColor);
                this.clickSize = JSON.parse(this.canvasDraw.clickSize);
                this.clickTool = JSON.parse(this.canvasDraw.clickTool);
                this.Text = JSON.parse(this.canvasDraw.Text);
            }
        },
        updateCurrentFile(file) {
            this.currentFile = file;
            this.currentFileId = file.id;
            this.buildCanvas();
        },
        setColor(color) {
            if (this.write) {
                return;
            }
            this.currentColor = color;
            this.currentColorRGBA = this.colors[color];
        },
        setSize(size) {
            if (this.textInput) {
                return;
            }
            this.currentSize = this.sizes[size];
        },
        setTool(tool) {
            if (this.write) {
                this.clickX.pop();
                this.clickY.pop();
                this.clickDrag.pop();
                this.clickColor.pop();
                this.clickSize.pop();
                this.clickTool.pop();
                this.write = false;
                this.textInput = false;
            }
            this.currentTool = this.tools[tool];
        },
        reset() {
            this.clickX.length = 0;
            this.clickY.length = 0;
            this.clickDrag.length = 0;
            this.clickColor.length = 0;
            this.clickSize.length = 0;
            this.clickTool.length = 0;
            this.Text.length = 0;
            this.paint = false;
            this.write = false;
            this.textInput = false;
            this.redraw();
        },
        buildCanvas() {
            let blockElem = this.$refs.block;
            let image = this.$refs.image;
            let canvas = this.$refs.canvas;
            canvas.width = blockElem.offsetWidth - 2;
            if (this.currentImage === 'true' && image.height > 0) {
                canvas.height = Math.round((canvas.width / image.width) * image.height);
            } else {
                canvas.height = 500;
            }
            this.context = canvas.getContext('2d');
            this.currentColor = 'blue';
            this.currentColorRGBA = this.colors['blue'];
            this.currentSize = this.sizes['normal'];
            this.currentTool = this.tools['pen'];
            this.redraw();
        },
        redraw() {
            let view = this;
            let context = view.context;
            let clickX = view.clickX;
            let clickY = view.clickY;
            context.clearRect(0, 0, context.canvas.width, context.canvas.height); // Clears the canvas
            context.fillStyle = '#ffffff';
            context.fillRect(0, 0, context.canvas.width, context.canvas.height); // set background
            if (view.currentImage === 'true') {
                let outlineImage = new Image();
                outlineImage.src = this.currentUrl;
                context.drawImage(outlineImage, 0, 0, context.canvas.width, context.canvas.height);
            }

            context.lineJoin = 'round';
            for (var i = 0; i < clickX.length; i++) {
                if (view.clickTool[i] === 'pen') {
                    context.beginPath();
                    if (view.clickDrag[i] && i) {
                        context.moveTo(clickX[i - 1], clickY[i - 1]);
                    } else {
                        context.moveTo(clickX[i] - 1, clickY[i]);
                    }
                    context.lineTo(clickX[i], clickY[i]);
                    context.closePath();
                    context.strokeStyle = view.clickColor[i];
                    context.lineWidth = view.clickSize[i];
                    context.stroke();
                }
                if (view.clickTool[i] === 'text') {
                    let fontsize = view.clickSize[i] * 6;
                    context.font = fontsize + 'px Arial ';
                    context.fillStyle = view.clickColor[i];
                    context.fillText(view.Text[i], clickX[i], clickY[i] + fontsize);
                }
            }
        },
        mouseDown(e) {
            if (this.write) {
                let view = this;
                this.$refs.textInputField.focus();
                window.setTimeout(function () {
                    view.$refs.textInputField.focus();
                }, 0);
                return;
            }
            if (this.currentTool === 'pen') {
                this.paint = true;
                this.addClick(e.offsetX, e.offsetY, false);
                this.redraw();
            }
            if (this.currentTool === 'text') {
                this.write = true;
                this.addClick(e.offsetX, e.offsetY, false);
            }
        },
        mouseMove(e) {
            if (this.paint) {
                this.addClick(e.offsetX, e.offsetY, true);
                this.redraw();
            }
        },
        mouseUp(e) {
            this.storeDraw();
            this.paint = false;
        },
        touchStart(e) {
            e.preventDefault();
            if (this.write) {
                return;
            }
            let canvas = this.$refs.canvas;
            let mousePos = this.getTouchPos(canvas, e);
            if(this.currentTool == 'pen') {
                this.paint = true;
                this.addClick(mousePos.x, mousePos.y, false);
                this.redraw();
            }
            if(this.currentTool == 'text') {
                this.write = true;
                this.addClick(mousePos.x, mousePos.y, false);
            }
        },
        touchMove(e) {
            e.preventDefault();

            let canvas = this.$refs.canvas;
            let mousePos = this.getTouchPos(canvas, e);
            if(this.paint){
                this.addClick(mousePos.x, mousePos.y, true);
                this.redraw();
            }
        },
        touchEnd(e) {
            this.storeDraw();
            this.paint = false;
        },
        getTouchPos(canvasDom, touchEvent) {
            var rect = canvasDom.getBoundingClientRect();
            return {
                x: touchEvent.touches[0].clientX - rect.left,
                y: touchEvent.touches[0].clientY - rect.top
            };
        },
        addClick(x, y, dragging) {
            this.clickX.push(x);
            this.clickY.push(y);
            this.clickDrag.push(dragging);
            this.clickColor.push(this.currentColorRGBA);
            this.clickSize.push(this.currentSize);
            this.clickTool.push(this.currentTool);
            if (this.currentTool === 'text') {
                this.enableTextInput(x, y);
            } else {
                this.Text.push('');
            }
        },
        undo() {
            let dragging = this.clickDrag[this.clickDrag.length - 1];
            this.clickX.pop();
            this.clickY.pop();
            this.clickDrag.pop();
            this.clickColor.pop();
            this.clickSize.pop();
            this.clickTool.pop();
            if (this.write) {
                this.textInput = false;
                this.write = false;
            } else {
                this.Text.pop('');
            }
            if (dragging) {
                this.undo();
            }
            this.redraw();
        },
        enableTextInput(x, y) {
            let view = this;
            let fontsize = this.currentSize * 6;
            this.textInput = true;
            let input = this.$refs.textInputField;
            input.value = '';
            input.style.position = 'absolute';
            input.style.top = this.$refs.canvas.offsetTop + y + 'px';
            input.style.left = 320 + x + 'px';
            input.style.lineHeight = fontsize + 'px';
            input.style.fontSize = fontsize + 'px';
            input.style.width = '300px';
            window.setTimeout(function () {
                view.$refs.textInputField.focus();
            }, 0);
        },
        textInputKeyUp(e) {
            if (e.defaultPrevented) {
                return;
            }
            let key = e.key || e.keyCode;
            if (key === 'Enter' || key === 13) {
                this.Text.push(this.$refs.textInputField.value);
                this.textInput = false;
                this.write = false;
                this.redraw();
            }
            if (key === 'Escape' || key === 'Esc' || key === 27) {
                this.clickX.pop();
                this.clickY.pop();
                this.clickDrag.pop();
                this.clickColor.pop();
                this.clickSize.pop();
                this.clickTool.pop();
                this.textInput = false;
                this.write = false;
            }
        },
        async storeDraw() {
            let data = {};
            data.type = 'courseware-user-data-fields';
            data.id = this.block.relationships['user-data-field'].data.id;
            data.relationships = {};
            data.relationships.block = {};
            data.relationships.block.data = {};
            data.relationships.block.data.id = this.block.id;
            data.relationships.block.data.type = this.block.type;
            data.attributes = {};
            data.attributes.payload = {};
            data.attributes.payload.canvas_draw = {};
            data.attributes.payload.canvas_draw.clickX = JSON.stringify(this.clickX);
            data.attributes.payload.canvas_draw.clickY = JSON.stringify(this.clickY);
            data.attributes.payload.canvas_draw.clickDrag = JSON.stringify(this.clickDrag);
            data.attributes.payload.canvas_draw.clickColor = JSON.stringify(this.clickColor);
            data.attributes.payload.canvas_draw.clickSize = JSON.stringify(this.clickSize);
            data.attributes.payload.canvas_draw.clickTool = JSON.stringify(this.clickTool);
            data.attributes.payload.canvas_draw.Text = JSON.stringify(this.Text);

            await this.$store.dispatch('courseware-user-data-fields/update', data);
        },
        storeBlock() {
            let attributes = {};
            attributes.payload = {};
            attributes.payload.title = this.currentTitle;
            attributes.payload.image = this.currentImage;
            if (this.currentImage === 'true') {
                attributes.payload.file_id = this.currentFileId;
            } else {
                attributes.payload.file_id = '';
            }
            attributes.payload.upload_folder_id = this.currentUploadFolderId;
            attributes.payload.show_usersdata = this.currentShowUserData;

            this.updateBlock({
                attributes: attributes,
                blockId: this.block.id,
                containerId: this.block.relationships.container.data.id,
            });
        },
        async store() {
            let user = this.usersById({id: this.userId});
            let imageBase64 = this.context.canvas.toDataURL("image/jpeg", 1.0);
            let image = await fetch(imageBase64);
            let imageBlob = await image.blob();
            let file = {};
            file.attributes = {};
            if(this.currentImage === 'true') {
                file.attributes.name = (user.attributes["formatted-name"]).replace(/\s+/g, '_') + '_' + this.currentFile.attributes.name;
            } else {
                file.attributes.name = (user.attributes["formatted-name"]).replace(/\s+/g, '_') + '_' + this.block.attributes.title + '_' + this.block.id;
            }

            let img = false;
            try {
                 img = await this.createFile({
                    file: file,
                    filedata: imageBlob,
                    folder: {id: this.currentUploadFolderId}
                });
            }
            catch(e) {
                this.companionError({
                    info: this.$gettext('Es ist ein Fehler aufgetretten! Das Bild konnte nicht gespeichert werden.')
                });
                console.log(e);
            }
            if(img && img.type === 'file-refs') {
                this.companionSuccess({
                    info: this.$gettext('Das Bild wurde erfolgreich im Dateibereich abgelegt.')
                });
            }
        },
    },
};
</script>
