<template>
    <div class="login-box">
        <div class="login-logo auth-branding text-center border-0">
            <span class="brand-text font-weight-light text-white">
                Welcome to
                <!-- <b>Dr. Smith & Dr. Brown's Office</b>! -->
                <b>{{ lobbyProp.name }}</b>
            </span>
        </div>
        <v-stepper v-model="stepper">
            <v-stepper-header>
                <v-stepper-step :complete="stepper > 1" step="1">Check In</v-stepper-step>

                <v-divider></v-divider>

                <v-stepper-step :complete="stepper > 2" step="2">Test your webcam</v-stepper-step>

                <v-divider></v-divider>

                <v-stepper-step step="3">Meet your Doctor</v-stepper-step>
            </v-stepper-header>

            <v-stepper-items>
                <v-stepper-content step="2">
                    <p>
                        Please make sure your webcam is working. Accept the access request to your hardware on the top left to continue.
                        <br />Then, someone should be with you shortly.
                    </p>

                    <v-card class="mb-12" color="grey lighten-1" height="50vh">
                        <grid-layout
                            :layout="videoGridPreview"
                            :key="`preview_${uniqueId}`"
                            :col-num="maxCols"
                            :max-rows="maxRows"
                            :row-height="rowHeight"
                            :is-draggable="false"
                            :is-resizable="false"
                            :verticalCompact="true"
                            :margin="[gridPadding, gridPadding]"
                            :use-css-transforms="true"
                        >
                            <grid-item v-for="video in videoGridPreview" :key="video.id" :id="video.id" :x="video.x" :y="video.y" :w="video.w" :h="video.h" :i="video.i"></grid-item>
                        </grid-layout>
                    </v-card>

                    <v-btn color="primary" @click="gotoStep3" :disabled="!cameraWorkingConfirmed">Continue</v-btn>

                    <!-- <v-btn text @click="stepper = 1">Cancel</v-btn> -->
                </v-stepper-content>

                <v-stepper-content step="3">
                    <p>Great! Please wait a little, doctor should join shortly.</p>

                    <v-card class="mb-12" color="grey lighten-1" height="50vh">
                        <grid-layout
                            :layout="videoGrid"
                            :key="uniqueId"
                            :col-num="maxCols"
                            :max-rows="maxRows"
                            :row-height="rowHeight"
                            :is-draggable="false"
                            :is-resizable="false"
                            :verticalCompact="true"
                            :margin="[gridPadding, gridPadding]"
                            :use-css-transforms="true"
                        >
                            <grid-item v-for="video in videoGrid" :key="video.id" :id="video.id" :x="video.x" :y="video.y" :w="video.w" :h="video.h" :i="video.i"></grid-item>
                        </grid-layout>
                    </v-card>
                </v-stepper-content>
            </v-stepper-items>
        </v-stepper>
        <div style="display: none" ref="otContainer"></div>
    </div>
</template>

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

import VueGridLayout from "vue-grid-layout";

import VueSocketIO from "vue-socket.io";
import SocketIO from "socket.io-client";

Vue.use(
    new VueSocketIO({
        debug: true,
        connection: SocketIO(process.env.MIX_SOCKET_SERVICE_URL)
    })
);

export default {
    components: {
        GridLayout: VueGridLayout.GridLayout,
        GridItem: VueGridLayout.GridItem
    },
    props: {
        lobbyProp: {
            type: Object,
            default: {
                uid: null,
                name: "Base",
                pros: []
            }
        },
        meetingProp: {
            type: Object
        },
        clientUid: {
            type: String,
            required: true
        }
    },
    computed: {
        // prosList(){
        //     return [{
        //         name: 'Test',
        //         type: 'Cardiologist',
        //         uid: 'someuid'
        //     }]
        // }
    },
    data() {
        return {
            user: {
                firstName: "",
                lastName: "",
                dateOfBirth: null,
                targetLobbyProUid: ""
            },
            meetingUid: "",
            meetingName: sessionStorage.getItem("meeting_name") || "",
            stepper: 2,
            cameraWorkingConfirmed: false,
            loading: false,
            /* Copied */
            readyForUse: false,
            uniqueId: Math.floor(Math.random() * Math.floor(10000)),
            counter: 1,
            openTokSession: null,
            publisher: null,
            screenPublisher: null,
            subscribers: [],
            publisherReady: false,
            sessionConnected: false,
            accessDialogShown: false,
            videos: [],
            videoGrid: [],
            videoGridPreview: [],
            maxCols: 12,
            maxRows: 4,
            rowHeight: 240,
            gridPadding: 8,
            loadingInProgress: false,
            prosList: []
        };
    },
    sockets: {
        reconnect: function() {
            this.$socket.emit("userData", {
                user: {
                    uid: this.clientUid,
                    name: `${this.firstName} ${this.lastName}`,
                    type: "STRANGER"
                },
                meeting: {
                    uid: this.meetingUid,
                    lobby_uid: this.lobbyProp.uid
                },
                lobbies_uid_list: [`${this.lobbyProp.uid}`]
            });

            if (this.meetingUid) {
                this.$socket.emit("meetingJoined", {
                    lobby_uid: this.lobbyProp.uid,
                    meeting_name: this.meetingName,
                    meeting_uid: this.meetingUid,
                    user: {
                        name: `${this.firstName} ${this.lastName}`,
                        type: "STRANGER",
                        uid: this.clientUid
                    }
                });
            }
        }
    },
    watch: {
        publisherReady(val) {
            if (val && this.sessionConnected) this.publishToSession();
        },
        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.id"(val) {
            if (this.loadingInProgress) return;
            this.loadingInProgress = true;
            this.disconnect();

            if (val) {
                this.getToken({}, true);
            } else {
                this.loadingInProgress = false;
            }
        },
        stepper: {
            handler(newVal) {
                sessionStorage.setItem(`${this.meetingProp.uid}.step`, newVal);
            }
        }
    },
    methods: {
        initializePublisher() {
            this.publisher = OT.initPublisher(
                this.$refs.otContainer,
                {
                    insertMode: "append",
                    width: "100%",
                    height: "100%",
                    resolution: "1280x720",
                    frameRate: 30,
                    name: `${this.user.firstName} ${this.user.lastName}`,
                    style: {
                        nameDisplayMode: "on",
                        archiveStatusDisplayMode: "off"
                    }
                },
                error => {
                    if (error) {
                        alert(error.message);
                    } else {
                        this.publisherReady = true;
                        const cont = this.createVideoContainer(true);
                        this.$nextTick(() => {
                            cont.el = $(`#${cont.id}`)[0];
                            cont.el.appendChild(this.publisher.element);
                            cont.obj = this.publisher;
                            this.$set(cont, "self", true);
                            this.cameraWorkingConfirmed = true;

                            if (this.stepper == 3) {
                                this.gotoStep3();
                            }
                        });
                    }
                }
            );
            this.publisher.on({
                accessDialogOpened: e => {
                    this.accessDialogShown = true;
                },
                accessDialogClosed: e => {
                    this.accessDialogShown = false;
                }
            });
        },
        gotoStep3() {
            if (this.stepper != 3) {
                this.stepper = 3;
            }

            this.videoGridPreview = [];
            this.adjustVideoContainers();
            this.$nextTick(() => {
                const cont = this.videos[0];
                cont.el = $(`#${cont.id}`)[0];
                cont.el.appendChild(cont.obj.element);
                this.getToken();

                this.$socket.emit("meetingJoined", {
                    lobby_uid: this.lobbyProp.uid,
                    meeting_name: this.meetingName,
                    meeting_uid: this.meetingUid,
                    user: {
                        name: `${this.firstName} ${this.lastName}`,
                        type: "STRANGER",
                        uid: this.clientUid
                    }
                });
                $.ajax({
                    url: "/post-to-api-ajax",
                    method: "POST",
                    headers: {
                        "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content")
                    },
                    data: {
                        _api: "/api/meeting/startLobbyCall",
                        uid: this.meetingUid,
                        lobbyUid: this.lobbyProp.uid
                    },
                    success: data => {
                        if (!data.success) console.log(data.message);
                    }
                });
            });
        },
        /* Copied */
        disconnect() {
            if (!this.openTokSession) return;
            this.openTokSession.disconnect();
            this.openTokSession.off();
            this.videos = [];
            this.publisher.destroy();
            this.publisher = null;
            this.subscribers = [];
            this.publisherReady = false;
            this.$store.commit("setSessionConnectivityState", false);
            this.openTokSession = null;
            if (this.screenPublisher) {
                this.screenPublisher.destroy();
                this.screenPublisher = null;
            }
        },
        getToken() {
            // if (this.meeting.scheduledDate && !this.meeting.startedAt && this.meeting.scheduledDate > new Date() && (this.user.type === "guest" || !confirm("Meeting not started. Start it now?")))
            //     return;
            $.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.meetingUid
                },
                success: data => {
                    if (!data.success) {
                        alert(data.message);
                        return;
                    }
                    // this.$refs.initialModal.hide();
                    // if (!isAssociate) {
                    //     const user = Object.assign({}, this.user);
                    //     user.id = data.participantId;
                    //     user.name = data.participantName;
                    //     user.pin = data.participantPin;
                    //     this.$store.commit("setUser", user);
                    // }
                    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(jXhr.responseJSON.message);
                    }
                }
            });
        },
        createVideoContainer(preview = false) {
            let videoCont = {};
            videoCont.id = `${this.uniqueId}_video_${this.counter++}`;

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

            return videoCont;
        },
        adjustVideoContainers(preview = false) {
            let videoGrid;
            if (preview) {
                videoGrid = this.videoGridPreview = [];
            } else {
                videoGrid = this.videoGrid = [];
            }

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

            let cols = Math.ceil(Math.sqrt(this.videos.length));
            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 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;
                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.");
                        //window.location.reload();
                        //TODO: Kicked
                        // if (this.user.type === "associate") {
                        //     this.disconnect();
                        //     this.$store.dispatch("leaveMeeting");
                        // } else {
                        //     window.location = "/";
                        // }
                    }
                }
            });

            // 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 screenshare
                }
                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);
            });

            /* console.log(sessionId);
            console.log(token);
            console.log(apiKey); */
            this.openTokSession.connect(token, error => {
                // If the connection is successful, publish to the session
                if (error) {
                    alert(error.message);
                } else {
                    this.sessionConnected = true;
                }
            });
            this.loadingInProgress = false;
        },
        publishToSession() {
            this.openTokSession.publish(this.publisher, error => {
                if (error) {
                    alert(error.message);
                }
            });
        },
        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
                });
            });
        }
    },
    created() {
        if (this.meetingProp) {
            this.user.firstName = this.meetingProp.strangerFirstName;
            this.user.lastName = this.meetingProp.strangerLastName;
            this.user.dateOfBirth = this.meetingProp.strangerDob;

            if (this.stepper == 1) {
                this.stepper = 2;
            }

            this.$socket.emit("userData", {
                user: {
                    uid: this.clientUid,
                    name: `${this.firstName} ${this.lastName}`,
                    type: "STRANGER"
                },
                meeting: {
                    uid: this.meetingUid,
                    lobby_uid: this.lobbyProp.uid
                },
                lobbies_uid_list: [`${this.lobbyProp.uid}`]
            });
            this.stepper = sessionStorage.getItem(`${this.meetingProp.uid}.step`) || 2;
        } else {
            window.location = "/";
        }
    },
    mounted() {
        if (this.meetingProp) {
            this.meetingUid = this.meetingProp.uid;
            this.$nextTick(this.initializePublisher);
            let self = this;
        }

        this.sockets.subscribe("meeting-closed", data => {
            this.$eventBus.$emit("leaveMeeting");
        });

        let self = this;

        this.$eventBus.$on("meetingRejoin", () => {
            this.loadingInProgress = 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", () => {
            $.ajax({
                url: "/post-to-api-ajax",
                method: "POST",
                headers: {
                    "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content")
                },
                error: jXhr => {
                    console.error(getSingleError(jXhr));
                }
            });
            this.$store.dispatch("leaveMeeting");
            this.$socket.emit("meetingLeft");
            this.disconnect();
            alert("Meeting was Closed.");
        });
        this.prosList.push(...this.lobbyProp.pros);
    }
};
</script>

<style lang="scss" scoped>
.login-box {
    width: 100%;
}

.checkin-form {
    height: 200px;

    form {
        width: 75%;
    }
}
</style>