<!--
  - Copyright (c) 2022.
  - Author Peter Placzek (tada5hi)
  - For the full copyright and license information,
  - view the LICENSE file that was distributed with this source code.
  -->

<script>
import Vue from "vue";
import {getMessages} from "@/domains/chat-message/api";
import {changeResponseKeyCase} from "@/modules/api/utils";
import ChatMessage from "@/components/chat/message/ChatMessage";

export default {
    components: {
        ChatMessage
    },
    props: {
        room: Object
    },
    data() {
        return {
            listener: undefined,

            meta: {
                limit: 10,
                offset: 0
            },

            busy: false,
            items: [],

            messageContent: '',
            messageLastEditId: undefined,
            messageEditId: undefined,
        }
    },
    computed: {
        itemsSorted() {
            function compare(a,b) {
                const aDate = new Date(a.createdAt).getTime();
                const bDate = new Date(b.createdAt).getTime();

                return aDate === bDate ? 0 : (aDate < bDate ? -1 : 1)
            }

            return this.items.sort(compare);
        }
    },
    created() {
        this.$chat.socket.onAny(this.socketListener);
        //this.load();
    },
    beforeDestroy() {
        this.$chat.socket.offAny(this.socketListener);
    },
    methods: {
        async loadMore($state) {
            try {
                const items = await this.load();
                if(items.length < this.meta.limit) {
                    await $state.complete();
                } else {
                    await $state.loaded();
                }

                this.scrollTo();
            } catch (e) {
                await $state.complete();
            }
        },
        async load() {
            if(this.busy) return;

            this.busy = true;

            try {
                const len = this.items.length;
                const items = await getMessages({
                    filter: {
                        roomId: this.room.id
                    },
                    page: {
                        limit: this.meta.limit,
                        offset: len
                    }
                });

                if(len === 0) {
                    this.items = items;
                } else {
                    this.items.push(...items);
                }

                //this.meta.offset = this.meta.offset + this.meta.limit;

                this.busy = false;

                return items;
            } catch (e) {
                this.busy = false;

                throw e;
            }
        },

        // Chat Room - Ref methods

        push(message) {
            let index = this.items.findIndex(item => item.id === message.id);
            if(index === -1) {
                this.items.push(message);
                this.scrollTo();
            }
        },
        replace(message) {
            let index = this.items.findIndex(item => item.id === message.id);
            if(index !== -1) {
                for(let key in message) {
                    if(message.hasOwnProperty(key)) {
                        Vue.set(this.items[index], key, message[key]);
                    }
                }
            }
        },

        //
        scrollTo() {
            if(typeof this.$refs['chatMessages'] === 'undefined') return;
            const totalHeight = this.$refs['chatMessages'].scrollHeight;
            const distanceTop = this.$refs['chatMessages'].scrollTop + this.$refs['chatMessages'].clientHeight;
            const itemHeight = 50;

            if(totalHeight > (distanceTop + 2 * itemHeight)) {
                return;
            }

            this.$nextTick(() => {
                this.$refs['chatMessages'].scrollTop = this.$refs['chatMessages'].scrollHeight - this.$refs['chatMessages'].clientHeight;
            });
        },

        dropMessage(messageId) {
            this.items = this.items.filter(item => item.id !== messageId);
        },

        /*
        Event Handlers
         */
        handleEditAction(message) {
            this.$emit('edit', message);
        },

        handleMessageDroppedEvent(id) {
            this.dropMessage(id);
        },

        handleSocketMessageAddedEvent(data) {
            if(data.meta.roomId !== this.room.id) return;

            if(this.items.findIndex(item => item.id === data.id) !== -1) return;

            const message = changeResponseKeyCase(data.data);

            this.items.push(message);
            this.scrollTo();
        },
        handleSocketMessageUpdatedEvent(data) {
            if(data.meta.roomId !== this.room.id) return;

            if(this.messageLastEditId === data.id) {
                this.messageEditId = undefined;
                return;
            }

            const message = changeResponseKeyCase(data.data);

            let index = this.items.findIndex(item => item.id === message.id);
            if(index === -1) {
                this.items.push(message);
                this.scrollTo();
            } else {
                for(let key in message) {
                    if(message.hasOwnProperty(key)) {
                        Vue.set(this.items[index], key, message[key]);
                    }
                }
            }

            console.log('Handle messageUpdated event succeeded...')
        },
        handleSocketMessageDroppedEvent(data) {
            if(data.meta.roomId !== this.room.id) return;

            this.dropMessage(data.id);
        },

        socketListener(event, message) {
            console.log(event, message);
            switch (event) {
                case 'messageCreated':
                    this.handleSocketMessageAddedEvent(message);
                    break;
                case 'messageUpdated':
                    this.handleSocketMessageUpdatedEvent(message);
                    break;
                case 'messageDeleted':
                    this.handleSocketMessageDroppedEvent(message);
                    break;
            }
        },
    }
}
</script>
<template>
    <div class="room-messages" ref="chatMessages">
        <infinite-loading ref="infiniteLoading" style="height:50px" spinner="waveDots" direction="top" @infinite="loadMore"></infinite-loading>

        <div>
            <chat-message
                v-for="message in itemsSorted"
                @dropped="handleMessageDroppedEvent"
                @edit="handleEditAction"
                :message="message"
                :room="room"
                :message-edit-id="messageEditId"
                :key="message.id"></chat-message>
        </div>
    </div>
</template>
<style>
.room-messages {
    overflow-y: scroll;
    overflow-x: unset;
    height: 100%;
}
</style>
