<template>
    <div class="h-100" v-if="meeting.passwordRequired ? meeting.passwordProvided : true">
        <div v-if="accessDialogShown">Please allow access to camera and microphone</div>
        <div class="h-100" ref="videos">
            <transition-group tag="div" class="video-wrapper" name="tiles">
                <grid-layout
                    :layout="videoGrid"
                    :key="uniqueId"
                    :col-num="maxCols"
                    :max-rows="maxRows"
                    :row-height="rowHeight"
                    :is-draggable="true"
                    :is-resizable="true"
                    :verticalCompact="true"
                    :margin="[gridPadding, gridPadding]"
                    :use-css-transforms="true"
                >
                    <grid-item v-for="(video, index) in videoGrid" :key="video.id" :id="video.id" :x="video.x" :y="video.y" :w="video.w" :h="video.h" :i="video.i">
                        <v-btn :color="'#282e38'" fab large dark class="v-btn--kick" @click="kickParcitipant(video)" v-show="!video.video.self && user.type == 'PRO'">
                            <v-icon>mdi-account-remove</v-icon>
                        </v-btn>
                    </grid-item>
                </grid-layout>
            </transition-group>
            <!-- <div v-for="(video, index) in videos" :id="video.id" :key="video.id" @click="switchToFullSize(video, index)" :class="{'selected-high': video.id == bigMembersCountSelectedId, 'selected-low': lowMembersCountSelectedId == video.id}" class="video-container">
            </div>-->
        </div>
        <button class="unscale" @click="bigMembersCountSelectedId = null" v-show="bigMembersCountSelectedId !== null">
            <i class="mdi mdi-close"></i>
        </button>
        <div style="display:none" ref="otContainer">
            <!-- Container to catch OpenTok Elements before reattaching -->
        </div>
        <!-- <modal-questions ref="initialModal" @questionsAnswered="getToken" @ready="ready"></modal-questions> -->
    </div>
</template>

<script>
import { mapState } from "vuex";

import VueGridLayout from "vue-grid-layout";

export default {
    components: {
        GridLayout: VueGridLayout.GridLayout,
        GridItem: VueGridLayout.GridItem
    },
    computed: {
        ...mapState(["meeting", "user", "session", "meetingLoading"])
    },
    data() {
        return {
            readyForUse: false,
            uniqueId: Math.floor(Math.random() * Math.floor(10000)),
            counter: 1,
            openTokSession: null,
            publisher: null,
            subscribers: [],
            publisherReady: false,
            accessDialogShown: false,
            videos: [],
            videoGrid: [],
            bigMembersCountSelectedId: null,
            lowMembersCountSelectedId: null,
            maxCols: 1,
            maxRows: 12,
            rowHeight: 120,
            gridPadding: 0
        };
    },
    methods: {
        disconnect() {
            if (!this.openTokSession) return;
            this.openTokSession.disconnect();
            this.openTokSession.off();
            this.videos = [];
            this.videoGrid = [];
            this.publisher.destroy();
            this.publisher = null;
            this.subscribers = [];
            this.publisherReady = false;
            this.$store.commit("setSessionConnectivityState", false);
            this.openTokSession = null;
        },
        getToken() {
            $.ajax({
                url: "/post-to-api-ajax",
                method: "POST",
                headers: {
                    "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content")
                },
                data: {
                    _api: "/api/meeting/getToken",
                    uid: this.meeting.uid
                },
                success: data => {
                    if (!data.success) {
                        alert(data.message);
                        return;
                    }
                    this.initializeOpenTok(data.data.apiKey, data.data.sessionId, data.data.token);
                },
                error: jXhr => {
                    if (jXhr.responseJSON && jXhr.responseJSON.errorCode) {
                        switch (jXhr.responseJSON.errorCode) {
                            case "LM-1":
                                alert("Meeting not started yet.");
                                break;
                            case "LM-2":
                                alert("You was kicked from this meeting.");
                                window.location = "/";
                                break;
                            case "LM-3":
                                alert("Wrong password");
                                this.$refs.initialModal.disableWaiting();
                                break;
                        }
                    } else {
                        this.$refs.initialModal.disableWaiting();
                        alert(getSingleError(jXhr));
                    }
                }
            });
        },
        createVideoContainer() {
            let videoCont = {};
            videoCont.id = `${this.uniqueId}_video_${this.counter++}`;
            if (this.videos.length == 1 && !this.lowMembersCountSelectedId) {
                this.lowMembersCountSelectedId = videoCont.id;
            }

            this.videos.push(videoCont);
            this.adjustVideoContainers();

            return videoCont;
        },
        adjustVideoContainers() {
            this.videoGrid = [];

            let windowHeight = window.innerHeight * 0.75;
            this.rowHeight = (windowHeight - this.gridPadding * (this.maxRows + 1)) / this.maxRows;

            //let cols = Math.ceil(Math.sqrt(this.videos.length));
            let cols = 1;
            let rows = Math.ceil(this.videos.length / cols);

            let elementsLastRow = this.videos.length % cols;
            let lastNormalIndex = this.videos.length - elementsLastRow;

            if (elementsLastRow) {
                this.maxCols = cols * elementsLastRow;
            } else {
                this.maxCols = cols;
            }

            //let colsPerElement = this.maxCols / cols;
            let rowsPerElement = this.maxRows / rows;

            let colsPerElement = 1;

            let colsLastRow = Math.ceil(this.maxCols / elementsLastRow);

            let cntX = 0;
            let cntY = 0;

            for (let [index, video] of this.videos.entries()) {
                video.i = index;
                video.x = cntX;
                video.y = cntY;
                video.h = rowsPerElement;
                video.w = colsPerElement;
                cntX += colsPerElement;

                if (cntX >= this.maxCols) {
                    cntX = 0;
                    cntY += rowsPerElement;
                }

                let videoTemp = Object.assign({}, video);
                videoTemp.video = video;
                this.videoGrid.push(videoTemp);
            }

            /* OLD IMPLEMENTATION */

            /* for (let [index, video] of this.videos.entries()) {
            video.i = index;
            if (index < lastNormalIndex) {
                video.x = cntX;
                video.y = cntY;
                video.h = rowsPerElement;
                video.w = colsPerElement;
                cntX += colsPerElement;

                if (cntX >= this.maxCols) {
                    cntX = 0;
                    cntY += rowsPerElement;
                }
            } else {
                video.x = cntX;
                video.y = cntY;
                video.h = rowsPerElement;
                video.w = colsLastRow;
                cntX += colsLastRow;
            }

            let videoTemp = Object.assign({}, video);
            this.videoGrid.push(videoTemp);
        } */

            /* let gridColumn, gridRows = ''

        if(rows && cols){
            gridColumn = `grid-template-columns: repeat(${cols}, minmax(320px, 1fr));`
            gridRows = `grid-template-rows: repeat(${rows}, minmax(240px, 1fr));`
        } */
        },
        initializeOpenTok(apiKey, sessionId, token) {
            this.openTokSession = OT.initSession(apiKey, sessionId);

            this.openTokSession.on({
                sessionDisconnected: event => {
                    if (event.reason === "forceDisconnected") {
                        alert("You were kicked out of meeting.");
                        this.$store.dispatch("leaveMeeting");
                    }
                }
            });

            // Create a publisher
            this.publisher = OT.initPublisher(
                this.$refs.otContainer,
                {
                    insertMode: "append",
                    width: "100%",
                    height: "100%",
                    resolution: "1280x720",
                    frameRate: 30,
                    name: this.user.name,
                    style: {
                        nameDisplayMode: "on",
                        archiveStatusDisplayMode: "off"
                    }
                },
                error => {
                    if (error) {
                        alert(error.message);
                    } else {
                        this.publisherReady = true;
                        const cont = this.createVideoContainer();
                        this.$nextTick(() => {
                            cont.el = $(`#${cont.id}`)[0];
                            cont.el.appendChild(this.publisher.element);
                            cont.obj = this.publisher;
                            this.$set(cont, "self", true);
                            //cont.self = true;
                        });
                    }
                }
            );

            this.publisher.on({
                accessDialogOpened: e => {
                    this.accessDialogShown = true;
                },
                accessDialogClosed: e => {
                    this.accessDialogShown = false;
                }
            });

            this.openTokSession.on("streamCreated", event => {
                //console.log("stream Created event");
                let container;
                if (event.stream.videoType === "screen") {
                    //TODO: This is
                }
                const subscriber = this.openTokSession.subscribe(
                    event.stream,
                    this.$refs.otContainer,
                    {
                        insertMode: "append",
                        width: "100%",
                        height: "100%",
                        style: { nameDisplayMode: "on" }
                    },
                    error => {
                        if (error) {
                            alert(error.message);
                        } else {
                            const cont = this.createVideoContainer();
                            this.$nextTick(() => {
                                cont.el = $(`#${cont.id}`)[0];
                                cont.el.appendChild(subscriber.element);
                                cont.obj = subscriber;
                                container = cont;
                            });
                        }
                    }
                );
                subscriber.on({
                    destroyed: e => {
                        container.el.remove();
                        const index = this.videos.findIndex(v => v.id == container.id);
                        if (index >= 0) this.videos.splice(index, 1);
                        this.adjustVideoContainers();
                    }
                });
                this.subscribers.push(subscriber);
            });

            this.openTokSession.connect(token, error => {
                // If the connection is successful, publish to the session
                if (error) {
                    alert(error.message);
                } else {
                    this.$store.commit("setSessionConnectivityState", true);
                }
            });
            this.$store.commit("setMeetingLoadingState", false);
        },
        publishToSession() {
            this.openTokSession.publish(this.publisher, error => {
                if (error) {
                    alert(error.message);
                }
            });
        },
        switchToFullSize(video, index) {
            if (this.videos.length < 4) {
                if (this.lowMembersCountSelectedId !== video.id && index !== 0) {
                    this.lowMembersCountSelectedId = video.id;
                }
            } else {
                this.bigMembersCountSelectedId = video.id;
            }
        },
        ready() {
            this.$nextTick(function() {
                this.readyForUse = true;
                if (this.user.type === "associate") {
                    if (!this.meeting.id) return;
                    this.getToken({}, true);
                    return;
                }

                if (this.meeting.scheduledDate && !this.meeting.startedAt && this.meeting.scheduledDate > new Date()) {
                    alert("Meeting not started.");
                    return;
                }
                let participantId = this.user.id;
                if (!participantId) {
                    this.$refs.initialModal.show(this.meeting.passwordRequired);
                    return;
                }
                this.getToken({
                    participantId
                });
            });
        },
        kickParcitipantContinue(participant) {
            const connection = participant.video.obj.stream.connection;
            const id = connection.data;
            this.openTokSession.forceDisconnect(connection, error => {
                if (error) {
                    console.error(error);
                } else {
                    $.ajax({
                        url: "/post-to-api-ajax",
                        method: "POST",
                        headers: {
                            "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content")
                        },
                        data: {
                            _api: "/api/meeting/kick",
                            uid: this.meeting.uid,
                            participantUid: id
                        },
                        success: data => {
                            if (!data.success) {
                                alert(data.message);
                                return;
                            }
                        },
                        error: jXhr => {
                            console.error(getSingleError(jXhr));
                        }
                    });
                }
            });
        },
        kickParcitipant(participant) {
            if (confirm("Are you sure want to kick this person out of meeting?")) this.kickParcitipantContinue(participant);
        },
        leaveMeeting() {
            $.ajax({
                url: "/post-to-api-ajax",
                method: "POST",
                headers: {
                    "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content")
                },
                data: {
                    _api: "/api/meeting/leave"
                },
                success: data => {
                    if (!data.success) {
                        alert(data.message);
                        return;
                    }
                    this.$store.dispatch("leaveMeeting");
                },
                error: jXhr => {
                    console.error(getSingleError(jXhr));
                }
            });
            this.$store.dispatch("leaveMeeting");
        }
    },
    watch: {
        publisherReady(val) {
            if (val && this.session.sessionConnected) this.publishToSession();
        },
        "session.sessionConnected"(val) {
            if (val && this.publisherReady) this.publishToSession();
        },
        "user.is_active_and_visible"(val) {
            if (!this.publisher || !this.publisher.publishVideo) return;
            this.publisher.publishVideo(val);
            this.publisher.publishAudio(val);
        },
        "meeting.uid"(val) {
            if (this.meetingLoading) return;
            this.$store.commit("setMeetingLoadingState", true);
            if (val) {
                this.getToken();
            } else {
                this.disconnect();
                this.$store.commit("setMeetingLoadingState", false);
            }
        }
    },
    mounted() {
        let self = this;

        this.$eventBus.$on("screenShare", this.shareScreen);
        this.$eventBus.$on("meetingRejoin", () => {
            this.$store.commit("setMeetingLoadingState", true);
            this.disconnect();
            this.getToken({}, true);
        });

        let width = $(window).width();
        let height = $(window).height();

        window.addEventListener("resize", function() {
            let new_width = $(window).width();
            let new_height = $(window).height();

            if (width !== new_width || height !== new_height) {
                self.adjustVideoContainers();
            }
        });

        this.$eventBus.$on("leaveMeeting", this.leaveMeeting);

        if (this.meeting.uid) {
            this.getToken();
        }
    }
};
</script>