<!--
  - 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 MultiSelect from "@/components/MultiSelect";
import {maxLength, minLength, required, requiredIf} from "vuelidate/lib/validators";
import {ChatRoomType, ChatRoomTypes} from "@/domains/chat-room/utils";
import {getUsers} from "@/domains/user/api";
import UserAvatar from "@/components/user/UserAvatar";
import {addContactRoom} from "@/domains/chat-room/contact/api";
import {addGroupRoom} from "@/domains/chat-room/group/api";
import {createAndShareRoomKeyToContacts} from "@/domains/chat-room/encryption";

const mustBeValidChatRoomType = (value) => {
    return ChatRoomTypes.indexOf(value) > -1;
}

export default {
    components: {
        UserAvatar,
        MultiSelect
    },
    data() {
        return {
            busy: false,
            message: undefined,

            form: {
                type: ChatRoomType.PRIVATE,
                name: '',
                description: '',
                protected: false,
                encryption: true,
                userIds: '',
                password: '',
            },

            types: [
                {id: ChatRoomType.PRIVATE, name: 'Privater Raum'},
                {id: ChatRoomType.GROUP, name: 'Gruppen Raum'},
                {id: ChatRoomType.CHANNEL, name: 'Channel'}
            ],
            typePrivate: ChatRoomType.PRIVATE,
            typeGroup: ChatRoomType.GROUP,
            typeChannel: ChatRoomType.CHANNEL,

            user: {
                items: [],
                busy: false,
                initialized: false,
                query: '',
                max: 1
            },

            useAccessKey: false,
            useContacts: false
        }
    },
    validations() {
        return {
            form: {
                name: {
                    required: requiredIf(function (form) {
                        return form.type !== ChatRoomType.PRIVATE;
                    }),
                    minLength: minLength(5),
                    maxLength: maxLength(30)
                },
                description: {
                    minLength: minLength(5),
                    maxLength: maxLength(2048)
                },
                userIds: {
                    required
                },
                protected: {
                    required
                },
                encryption: {
                    required
                },
                password: {
                    minLength: minLength(3),
                    maxLength: maxLength(100)
                },
                type: {
                    required
                }
            }
        }
    },
    created() {
        this.loadContacts();
    },
    watch: {
        roomType: function (val, oldVal) {
            switch (val) {
                case ChatRoomType.PRIVATE:
                    this.user.max = 1;
                    break;
                case ChatRoomType.GROUP:
                    this.user.max = 50;
                    break;
                case ChatRoomType.CHANNEL:
                    this.user.max = 5000;
                    break;
            }

            if(oldVal === ChatRoomType.CHANNEL && (val === ChatRoomType.PRIVATE || val === ChatRoomType.GROUP)) {
                this.form.userIds = val === ChatRoomType.PRIVATE ? '' : [];
                this.loadContacts();
            }

            if(val === ChatRoomType.CHANNEL && (oldVal === ChatRoomType.PRIVATE || oldVal === ChatRoomType.GROUP)) {
                this.loadContacts();
            }

            this.message = null;
        }
    },
    methods: {
        async submit() {
            if(this.busy) return;

            try {
                let room;

                let {userIds, ...form} = this.form;

                const prototype = Object.prototype.toString.call(userIds);
                if(prototype === '[object Object]') {
                    userIds = [userIds];
                }

                userIds = userIds.map(user => user.id);

                form = {userIds, ...form};

                switch (this.form.type) {
                    case ChatRoomType.PRIVATE:
                        room = await addContactRoom(form);
                        break;
                    case ChatRoomType.GROUP:
                        room = await addGroupRoom(form);
                        break;
                    case ChatRoomType.CHANNEL:
                        break;
                }

                if(room) {
                    if(room.type === ChatRoomType.GROUP) {
                        await createAndShareRoomKeyToContacts(room.id);
                    }

                    this.message = undefined;
                    this.$emit('created', room);
                }
            } catch (e) {
                this.message = e.message;
                this.$emit('creationFailed', e.message);
            }

            this.busy = false;
        },

        async loadContacts() {
            if(this.user.busy) return;

            this.user.busy = true;

            try {
                let filter = {
                    onlyContacts: this.form.type === ChatRoomType.PRIVATE || this.form.type === ChatRoomType.GROUP,
                    excludeSelf: true
                };

                if(this.user.query.trim() !== '') {
                    filter.name = '~'+this.user.query;
                }

                const response = await getUsers({
                    filter,
                    page: {
                        limit: 10
                    }
                });
                this.user.items = response.data;

                this.user.initialized = true;
            } catch (e) {

            }

            this.user.busy = false;
        },
        async findContacts(query) {
            this.user.query = query;
            await this.loadContacts();
        }
    },
    computed: {
        userId() {
            return this.$store.getters['auth/user'].id;
        },
        roomType() {
            return this.form.type;
        },
        selectedUserCount() {
            const prototype = Object.prototype.toString.call(this.form.userIds);
            switch (prototype) {
                case '[object Array]':
                    return this.form.userIds.length;
                case '[object Object]':
                    return 1;
            }

            return 0;
        }
    }
}
</script>
<template>
    <form name="room-form" @submit.prevent="submit">
        <div v-if="message" class="alert alert-sm alert-warning">
            {{message}}
        </div>

        <div class="row">
            <div class="col-5">
                <h6>Core</h6>

                <div class="form-group">
                    <label>Type</label>
                    <select class="form-control" v-model="$v.form.type.$model">
                        <option v-for="(item,key) in types" :key="key" :value="item.id">
                            {{item.name}}
                        </option>
                    </select>
                    <div v-if="!$v.form.type.required && !$v.form.type.$model" class="alert alert-warning alert-sm">
                        Bitte wähle einen Type aus...
                    </div>
                </div>

                <div class="row">
                    <template v-if="form.type === typePrivate">
                        <img class="w-100" src="~assets/img/Conversation-pana.png" />

                        <h6 class="text-center">Private Raum</h6>

                        <p>
                            Private Räume ermöglichen es zwischen zwei Benuztern
                            eines Kontaktes zu kommunizieren.
                        </p>
                    </template>
                    <template v-else-if="form.type === typeGroup">
                        <img class="w-100" src="~assets/img/Group Chat-rafiki.png" />

                        <h6 class="text-center">Gruppen Raum</h6>

                        <p>
                            Gruppen Räume ermöglichen es zwischen mehreren Benutzern, die auf irgendeine
                            Weise über Kontaktbeziehungen miteinander verbunden sind, zu kommunizieren.
                        </p>
                    </template>
                    <template v-else-if="form.type === typeChannel">
                        <img class="w-100" src="~assets/img/Work chat-amico.png" />

                        <h6 class="text-center">Channel</h6>

                        <p>
                            Channels sind sogenannte öffentliche Räume und sofern kein Passwort oder der Raum
                            auf andere Weise geschützt wird, beigetreten werden.
                        </p>
                    </template>
                </div>
            </div>
            <div class="col-7">
                <h6>Allgemein</h6>

                <!-- Name -->

                <div v-if="form.type !== typePrivate" class="form-group" :class="{ 'form-group-error': $v.form.name.$error }">
                    <label>Name</label>
                    <input v-model="$v.form.name.$model" type="text" name="name" class="form-control" placeholder="Name...">

                    <div v-if="!$v.form.name.required && !$v.form.name.$model" class="form-group-hint group-required">
                        Bitte geben Sie einen Namen an.
                    </div>
                    <div v-if="!$v.form.name.minLength" class="form-group-hint group-required">
                        Der Name muss mindestens <strong>{{ $v.form.name.$params.minLength.min }}</strong> Zeichen lang sein.
                    </div>
                    <div v-if="!$v.form.name.maxLength" class="form-group-hint group-required">
                        Der Name darf maximal <strong>{{ $v.form.name.$params.maxLength.max }}</strong> Zeichen lang sein.
                    </div>
                </div>

                <!-- Description -->

                <div v-if="form.type !== typePrivate" class="form-group" :class="{ 'form-group-error': $v.form.description.$error }">
                    <label>Beschreibung</label>
                    <textarea v-model="$v.form.description.$model" class="form-control" rows="4" placeholder="Gib eine Beschreibung an..."></textarea>

                    <div v-if="!$v.form.description.minLength" class="form-group-hint group-required">
                        Die Beschreibung muss mindestens <strong>{{ $v.form.name.$params.minLength.min }}</strong> Zeichen lang sein.
                    </div>
                    <div v-if="!$v.form.description.maxLength" class="form-group-hint group-required">
                        Die Beschreibung darf maximal <strong>{{ $v.form.name.$params.maxLength.max }}</strong> Zeichen lang sein.
                    </div>
                </div>

                <div class="form-group" :class="{ 'form-group-error': $v.form.userIds.$error }">
                    <label>Kontakte <small class="text-success">({{selectedUserCount}}/{{ user.max }})</small></label>

                    <multi-select
                        placeholder="Suchen..."
                        open-direction="bottom"
                        :multiple="true"
                        :searchable="true"
                        :internal-search="false"
                        :clear-on-select="false"
                        :close-on-select="form.type === typePrivate"
                        :options-limit="10"
                        :limit="3"
                        :max="user.max"
                        :max-height="600"
                        :show-no-results="true"
                        :hide-selected="false"
                        @search-change="findContacts"
                        :loading="user.busy"
                        v-model="$v.form.userIds.$model"
                        track-by="id"
                        label="name"
                        :options="user.items">
                        <template slot="option" slot-scope="props">
                            <div class="d-flex flex-row align-items-center">
                                <div class="mr-2">
                                    <user-avatar :size="'1.5rem'" :name="props.option.name" :avatar="props.option.avatar" :email="props.option.email" />
                                </div>
                                <div>
                                    {{props.option.name}}
                                </div>
                            </div>
                        </template>
                    </multi-select>

                    <div v-if="!$v.form.userIds.required && !$v.form.userIds.$model" class="form-group-hint group-required">
                        Bitte wähle eine Person aus.
                    </div>
                </div>

                <hr />

                <h6>Sicherheit</h6>
                <div v-if="form.type === typeChannel" class="mb-2">
                    <b-form-checkbox v-model="$v.form.protected.$model" :disabled="busy" switch>
                        <i class="fa fa-lock text-success"></i> Schutz
                    </b-form-checkbox>

                    <p>
                        Den Raum nur für Personen zulassen, die das Passwort oder eine Einladung besitzen.
                    </p>
                </div>

                <div v-if="form.type === typeChannel" class="form-group" :class="{ 'form-group-error': $v.form.password.$error }">
                    <label>Passwort</label>
                    <input v-model="$v.form.password.$model" type="text" name="name" class="form-control" :disabled="!form.protected" placeholder="Passwort...">

                    <div v-if="!$v.form.name.minLength" class="form-group-hint group-required">
                        Das Passwort muss mindestens <strong>{{ $v.form.password.$params.minLength.min }}</strong> Zeichen lang sein.
                    </div>
                    <div v-if="!$v.form.name.maxLength" class="form-group-hint group-required">
                        Der Passwort darf maximal <strong>{{ $v.form.password.$params.maxLength.max }}</strong> Zeichen lang sein.
                    </div>
                </div>

                <div v-if="form.type !== typeChannel" class="mb-2">
                    <b-form-checkbox v-model="$v.form.encryption.$model" :disabled="busy" switch>
                        <i class="fa fa-lock text-success"></i> Verschlüsselung
                    </b-form-checkbox>

                    <p>
                        Mit Hilfe der Verschlüsselung werden Nachrichten innerhalb des Chat Raumes End-zu-Ende verschlüsselt.
                    </p>
                </div>

                <hr />

                <button type="submit" class="btn btn-primary btn-sm" @click.prevent="submit" :disabled="$v.form.$invalid">
                    <i class="fa fa-hammer"></i> Erstellen
                </button>
            </div>
        </div>
    </form>
</template>
