<template>
    <div id="media-library">
        <div class="container-fluid">
            <div class="row no-gutters">
                <div class="close-window" @click="onCloseWindow"><i class="fa fa-close"></i></div>
                <div class="col-md-2 col-categories" v-show="!isMobile || _d.onlyShowCategory">
                    <div class="row row-head no-gutters">
                        <div class="col">
                            <div class="controls">
                                <div v-if="_d.addingNewCategory">
                                    <input type="text" class="form-control" v-model="_d.currentEditingCategoryText" @click.prevent.stop @keypress.enter="onAddCategory">
                                    <button class="btn btn-sm btn-success" @click.prevent.stop="onAddCategory"><i class="fa fa-check"></i></button>
                                    <button class="btn btn-sm btn-outline-secondary" @click.prevent.stop="onCancelCategoryAdding"><i class="fa fa-close"></i></button>
                                </div>
                                <div v-if="!_d.addingNewCategory">
                                    <button class="btn btn-success btn-sm" @click="_d.addingNewCategory=true"><i class="fa fa-plus"></i></button>
                                    <button class="btn btn-primary btn-sm" @click="onEditCategory(_d.currentCategory)"><i class="fa fa-edit"></i></button>
                                    <button class="btn btn-danger btn-sm" @click="onDeleteCategory(_d.currentCategory)"><i class="fa fa-close"></i></button>
                                    <button class="btn btn-outline-secondary btn-sm return" v-if="isMobile" @click="_d.onlyShowCategory=false"><i class="fa fa-arrow-right"></i></button>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="row row-body no-gutters">
                        <div class="col">
                            <div class="category-list-wrapper">
                                <div class="message">
                                    <div class="alert alert-success" v-if="_d.categorySuccessMessage">{{ _d.categorySuccessMessage }}</div>
                                    <div class="alert alert-danger" v-if="_d.categoryErrorMessage">
                                        {{ _d.categoryErrorMessage }}
                                        <button type="button" class="close" aria-label="Close" @click="_d.categoryErrorMessage=null">
                                            <span aria-hidden="true">&times;</span>
                                        </button>
                                    </div>
                                </div>
                                <div class="spinner-border" role="status" v-if="_d.categoryFetching">
                                    <span class="sr-only">Loading...</span>
                                </div>
                                <nav class="nav flex-column category-list" :class="{dragging: this._d.currentDraggingCategoryId}" ref="categoryList">
                                    <a class="nav-link category"
                                       href="#"
                                       :draggable="!isUneditableCategory(category.id)"
                                       :data-id="category.id"
                                       :class="{current: _d.currentCategory == category.id, editing: isCategoryEditing(category.id)}"
                                       @dragenter.capture.prevent.stop="onDragEnterCategory($event, category.id)"
                                       @dragleave.capture.prevent.stop="onDragLeaveCategory($event)"
                                       @drop="onDropOnCategory($event, category.id)"
                                       @dragstart.stop="onDragCategory(category.id)"
                                       @dragover.prevent.stop
                                       @dragend.capture.prevent.stop="onDropCategory"
                                       @click.prevent="switchCategory(category.id)"
                                       v-for="category in _d.categories">
                                <span v-if="!isCategoryEditing(category.id)">
                                    <span class="name">{{ category.name }}</span>
                                    <span class="badge badge-secondary">{{ category.count }}</span>
                                    <button class="btn btn-sm edit-category" v-if="!isUneditableCategory(category.id)" @click.prevent.stop="onEditCategory(category.id)">
                                        <i class="fa fa-edit"></i>
                                    </button>
                                     <button class="btn btn-sm remove-category" v-if="!isUneditableCategory(category.id)" @click.prevent.stop="onDeleteCategory(category.id)">
                                        <i class="fa fa-close"></i>
                                    </button>
                                </span>
                                        <span v-if="isCategoryEditing(category.id)">
                                    <input type="text" class="form-control" v-model="_d.currentEditingCategoryText" @click.prevent.stop>
                                    <button class="btn btn-sm btn-primary" @click.prevent.stop="onUpdateCategoryName()"><i class="fa fa-check"></i></button>
                                    <button class="btn btn-sm btn-outline-secondary" @click.prevent.stop="cancelCategoryEditing"><i class="fa fa-close"></i></button>
                                </span>
                                    </a>
                                </nav>
                            </div>
                        </div>
                    </div>
                    <div class="row row-footer no-gutters">
                        <div class="col"></div>
                    </div>
                </div>
                <div class="col col-images" v-show="!isMobile || (isMobile && !_d.onlyShowCategory && !_d.onlyShowMediaInfo)">
                    <div class="row row-head no-gutters">
                        <div class="col">
                            <ul class="nav nav-tabs tabs">
                                <li class="nav-item" v-if="isMobile">
                                    <a href="#" class="nav-link" @click="_d.onlyShowCategory=true">
                                        {{ _d.text.tabCategory }}
                                    </a>
                                </li>
                                <li class="nav-item">
                                    <a class="nav-link" href="#" @drag.prevent @click="_d.isUploadingPage=true"
                                       v-bind:class="{active: _d.isUploadingPage}">{{ _d.text.tabUpload }}</a>
                                </li>
                                <li class="nav-item">
                                    <a class="nav-link" href="#" @drag.prevent @click="_d.isUploadingPage=false"
                                       v-bind:class="{active: !_d.isUploadingPage}">{{ _d.text.tabBrowse }}</a>
                                </li>
                            </ul>
                        </div>
                    </div>
                    <div class="row row-body no-gutters">
                        <div class="col">
                            <div class="alert alert-success image-message" v-if="_d.imageSuccessMessage">
                                {{ _d.imageSuccessMessage }}
                            </div>
                            <div class="alert alert-danger image-message" v-if="_d.imageErrorMessage">
                                {{ _d.imageErrorMessage }}
                                <button type="button" class="close" aria-label="Close" @click="_d.imageErrorMessage=null">
                                    <span aria-hidden="true">&times;</span>
                                </button>
                            </div>
                            <div class="tab-page upload" v-show="_d.isUploadingPage">
                                <form class="upload-zone" v-bind:action="_d.formAction" ref="uploadZone">
                                    <input type="hidden" name="_token" v-bind:value="_d.csrfToken">
                                    <div class="fallback">
                                        <input name="media_file" type="file" multiple />
                                    </div>
                                    <div class="upload-tip"> {{ _d.text.dragOrClickToUpload }} </div>
                                </form>
                            </div>
                            <div class="tab-page browse" v-bind:class="{dragging : !isCurrentDraggingMediaIdsEmpty }" v-show="!_d.isUploadingPage" @scroll="onScrollBrowsing($event)">
                                <div v-for="media in _d.medias"
                                     :key="media.id"
                                     @dragend="onDropMedia"
                                     @dragstart="onDragMedia(media.id)"
                                     draggable="true"
                                     class="img-wrapper"
                                     v-bind:class="{ selected: isMediaSelected(media)}"
                                     @click="onClickMedia($event, media)"
                                     @click.ctrl="onCtrlClickMedia($event, media)">
                                    <div class="img" :style="{ 'background-image': 'url(' + media.url + ')' }">
                                    </div>
                                </div>
                                <div class="spinner-border" role="status" v-if="_d.fetchingLock">
                                    <span class="sr-only">Loading...</span>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="row row-footer no-gutters">
                        <div class="col"></div>
                    </div>
                </div>
                <div class="col-md-2 col-media-info" v-show="!isMobile || _d.onlyShowMediaInfo">
                    <div class="row row-head" v-if="isMobile">
                        <div class="col">
                            <button class="btn btn-outline-secondary btn-sm return" @click="_d.onlyShowMediaInfo=false"><i class="fa fa-arrow-left"></i></button>
                        </div>
                    </div>
                    <div class="row row-body no-gutters">
                        <div class="col">
                            <div class="media-info-wrapper" :class="{'select-mode': _d.selectMode}">
                                <div class="message">
                                    <div class="alert alert-danger" v-if="_d.infoErrorMessage">
                                        {{ _d.infoErrorMessage }}
                                        <button type="button" class="close" aria-label="Close" @click="_d.infoErrorMessage=null">
                                            <span aria-hidden="true">&times;</span>
                                        </button>
                                    </div>
                                    <div class="alert alert-success" v-if="_d.infoSuccessMessage">{{ _d.infoSuccessMessage }}</div>
                                </div>
                                <div class="info" :class="{hidden: !_d.currentSelectedMedia}">
                                    <div class="url">
                                        <span class="label font-weight-bold">{{ _d.text.url }} :</span>
                                        <div class="content">
                                            <a v-bind:href="_d.currentSelectedMedia.url" target="_blank">{{ _d.currentSelectedMedia.url }}</a>
                                        </div>
                                    </div>
                                    <div class="size">
                                        <span class="label font-weight-bold">{{ _d.text.fileSize }}:</span>
                                        <span class="content">{{ fileSize }}</span>
                                    </div>
                                    <div class="date">
                                        <span class="label font-weight-bold">{{ _d.text.date }}:</span>
                                        <span class="content">{{ _d.currentSelectedMedia.date }}</span>
                                    </div>
                                    <div class="dimension">
                                        <span class="label font-weight-bold">{{ _d.text.size }}:</span>
                                        <span class="content">{{ dimension }}</span>
                                    </div>
                                    <div class="category">
                                        <span class="label font-weight-bold">{{ _d.text.category }}:</span>
                                        <select name="" id="" v-model="_d.currentSelectedMedia.category.id" v-if="_d.currentSelectedMedia.category">
                                            <option :value="category.id" v-for="category in this.mediaSettableCategories">{{ category.name }}</option>
                                        </select>
                                        <button class="btn btn-success btn-sm" @click.prevent="onUpdateMediaCategory()" v-if="_d.currentSelectedMedia">{{ _d.text.update }}</button>
                                    </div>
                                    <div class="description">
                                        <span class="label font-weight-bold">{{ _d.text.description }}</span>
                                        <div class="content">
                                            <textarea class="form-control" v-model="_d.currentSelectedMedia.description"></textarea>
                                        </div>
                                        <button class="btn btn-success btn-sm" @click.prevent="onUpdateMediaDescription($event)">{{ _d.text.update }}</button>
                                        <button class="btn btn-outline-danger btn-sm" @click.prevent="onDeleteMedia($event)">{{ _d.text.delete }}</button>
                                    </div>
                                    <div class="img">
                                        <img v-bind:src="_d.currentSelectedMedia.url" alt="">
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="row row-footer no-gutters">
                        <div class="col">
                            <div class="select-medias" v-if="_d.selectMode">
                                <button class="btn btn-primary" @click="onDoneSelectedMedias" :disabled="isSelectedMediasEmpty">{{ _d.text.select }}</button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "media-library",
        props: ['_d'],
        computed: {
            isMobile() {
                let isMobile = this._d.windowWidth < 768;
                return isMobile;
            },
            mediaSettableCategories() {
                return this._d.categories.filter(category => !this.isAllCategory(category.id));
            },
            // 是否為單選模式
            isSingleSelectionMode() {
                return this._d.single;
            },
            isSelectedMediasEmpty() {
                return this._d.selectedMedias.length ? false : true;
            },
            selectedMediaIds() {
                return this._d.selectedMedias.map(_media => _media.id);
            },
            isCurrentDraggingMediaIdsEmpty() {
                return this._d.currentDraggingMediaIds ? false : true;
            },
            dimension() {
                if(this._d.currentSelectedMedia.width !== null && this._d.currentSelectedMedia.height !== null) {
                    return this._d.currentSelectedMedia.width + 'x' + this._d.currentSelectedMedia.height;
                } else {
                    return '';
                }
            },
            fileSize() {
                if(this._d.currentSelectedMedia.sizeInBytes) {
                    let size = this._d.currentSelectedMedia.sizeInBytes;

                    if(size < 1024)
                        return size + ' Bytes';

                    let unit = 0;
                    while(size >= 1024) {
                        unit++;
                        size /= 1024;
                    }
                    size = parseFloat(size).toFixed(2)

                    switch(unit) {
                        case 1:
                            size += ' KB';
                            break;
                        case 2:
                            size += ' MB';
                            break;
                        case 3:
                            size += ' GB';
                            break;
                    }
                    return size;
                }
                return '';
            }
        },
        methods: {
            // 設定已選擇的媒體
            setSelectedMedias(selectedMedias) {
                this._d.selectedMedias = selectedMedias;
            },
            // 清空被選擇的媒體
            clearSelectedMedia() {
                this.setSelectedMedias([]);
            },
            // 加入媒體至被選擇的媒體中
            addToSelectedMedia(media) {
                this._d.selectedMedias.push(media)
            },
            // 媒體是否已被選擇(by ID)
            isMediaIdSelected(id) {
                let foundMedias = this._d.selectedMedias.find(_media => _media.id == id);
                return foundMedias ? true : false;
            },
            // 媒體是否已被選擇
            isMediaSelected(media) {
                return this.isMediaIdSelected(media.id);
            },
            // 從被選擇的媒體中刪除媒體
            deleteFromSelectedMedia(media) {
                this.setSelectedMedias(this._d.selectedMedias.filter(_media => _media.id != media.id));
            },
            // 從被選擇的媒體中刪除或新增媒體
            addOrDeleteSelectedMedia(media) {
                if(this.isMediaSelected(media)) {
                    this.unselectMedia(media);
                } else {
                    this.addToSelectedMedia(media);
                }
            },
            // 設定單一個媒體至被選擇的媒體
            setSingleSelectedMedia(media) {
                this.clearSelectedMedia();
                this.addToSelectedMedia(media);
                this.setCurrentSelectedMedia(media);
            },
            // 反選擇媒體
            unselectMedia(media) {
                this.deleteFromSelectedMedia(media);
                this.clearCurrentSelectedMedia();
            },
            // 清除目前點選的媒體
            clearCurrentSelectedMedia() {
                this._d.currentSelectedMedia = false
            },
            // 設定目前點選的媒體
            setCurrentSelectedMedia(media) {
                this._d.currentSelectedMedia = media;
                if(this.isMobile) {
                    this._d.onlyShowMediaInfo = true;
                }
            },
            // 取得媒體資料
            findMedia(id) {
                return this._d.medias.find(media => media.id == id);
            },
            // 分類ID為"所有"
            isAllCategory(id) {
                return id == 'all';
            },
            // 分類ID為"未分類"
            isUncategorizedCategory(id) {
                return id == 'uncategorized';
            },
            // 無法編輯的分類
            isUneditableCategory(id) {
                return this.isUncategorizedCategory(id) || this.isAllCategory(id)
            },
            // 特定ID的分類正在編輯
            isCategoryEditing(id) {
                return this._d.currentEditingCategory == id;
            },
            // 取得分類資料
            findCategory(id) {
                return this._d.categories.find(category => category.id == id);
            },
            // 取得分類名稱
            getCategoryName(id) {
                let category = this.findCategory(id);
                return category ? category.name : null;
            },
            // 刪除媒體
            removeMediaFromList(mediaId) {
                this._d.medias = this._d.medias.filter(media => media.id != mediaId);
                if(this._d.currentSelectedMedia.id == mediaId) {
                    this.clearCurrentSelectedMedia();
                }
            },
            // click事件，選擇媒體
            onClickMedia(e, media, fromMulti = false) {
                if(e.ctrlKey && !fromMulti) {
                    return;
                }
                if(
                    (this.isSingleSelectionMode && this.isMediaSelected(media)) ||
                    (!this.isSingleSelectionMode && this.isMediaSelected(media) && this._d.selectedMedias.length == 1)
                ) {
                    this.unselectMedia(media);
                } else {
                    this.setSingleSelectedMedia(media);
                }
            },
            // click事件，多選媒體
            onCtrlClickMedia(e, media) {
                this.setCurrentSelectedMedia(media);
                if(this.isSingleSelectionMode) {
                    this.onClickMedia(e, media, true);
                } else {
                    this.addOrDeleteSelectedMedia(media);
                }
            },
            // click事件，回傳選擇的媒體
            onDoneSelectedMedias() {
                let data = [], idString = '';
                this._d.selectedMedias.forEach(_media => {
                    data.push({
                        id: _media.id,
                        url: _media.url
                    })
                })
                idString = data.map(media => media.id).join(',')

                this.$root.$emit('media_selected', {
                    idString: idString,
                    medias: data
                })
                this.onCloseWindow();
            },
            // click事件，關閉視窗
            onCloseWindow() {
                this.$root.$emit('close');
            },
            onUpdateMediaCategory() {
                this.$root.$emit('update_category_for_medias', this._d.currentSelectedMedia.category.id, this._d.currentSelectedMedia.id, false);
            },
            // click事件，更新媒體描述
            onUpdateMediaDescription(e) {
                this.$root.$emit('update_media_description', e, this._d.currentSelectedMedia)
            },
            // click事件，刪除媒體
            onDeleteMedia(e) {
                this.$root.$emit('delete_media', e, this._d.currentSelectedMedia)
            },
            // 更新媒體的分類名稱
            updateCategoryForMedia(mediaId, categoryId) {
                let media = this._d.medias.find(media => media.id == mediaId);
                if(media) {
                    let category = this.findCategory(categoryId);
                    if(category) {
                        media.category.name = category.name;
                        media.category.id = categoryId;
                    }
                }
            },
            // 設定目前正在拖曳的媒體ID
            setCurrentDraggingMediaIds(ids) {
                this._d.currentDraggingMediaIds = ids;
            },
            // 清除目前正在拖曳的媒體ID
            clearCurrentDraggingMediaIds() {
                this._d.currentDraggingMediaIds = null;
            },
            // click事件，刪除所有選擇的媒體
            deleteSelectedMedias() {
                //TODO 批次刪除媒體
            },
            // scroll事件，載入更多媒體
            onScrollBrowsing(e) {
                if(this._d.fetchingEnd) return;
                let ele = e.target;
                if(ele.scrollTop >= ele.scrollHeight - ele.clientHeight - 10) {
                    if(!this._d.fetchingLock) {
                        this.$root.$emit('fetch_medias', 14);
                    }
                }
            },
            clearInfoMessages() {
                this._d.infoSuccessMessage = '';
                this._d.infoErrorMessage = '';
            },
            showInfoSuccessMessage(message) {
                this._d.infoSuccessMessage = message;
                setTimeout(() => {
                    this._d.infoSuccessMessage = '';
                }, 5000);
            },
            showInfoErrorMessage(message) {
                this._d.infoErrorMessage = message;
            },
            clearCategoryMessages() {
                this._d.categorySuccessMessage = '';
                this._d.categoryErrorMessage = '';
            },
            showCategorySuccessMessage(message) {
                this._d.categorySuccessMessage = message;
                setTimeout(() => {
                    this._d.categorySuccessMessage = '';
                }, 1000);
            },
            showCategoryErrorMessage(message) {
                this._d.categoryErrorMessage = message;
            },
            clearImageMessages() {
                this._d.imageSuccessMessage = '';
                this._d.imageErrorMessage = '';
            },
            showImageSuccessMessage(message) {
                this._d.imageSuccessMessage = message;
                setTimeout(() => {
                    this._d.imageSuccessMessage = '';
                }, 1000);
            },
            showImageErrorMessage(message) {
                this._d.imageErrorMessage = message;
            },
            // drag事件，拖曳媒體
            onDragMedia(id) {
                if(!this.isSelectedMediasEmpty && this.isMediaIdSelected(id)) {
                    this.setCurrentDraggingMediaIds(this.selectedMediaIds);
                } else {
                    this.setCurrentDraggingMediaIds(id);
                }
            },
            // dragenter事件，拖曳媒體或分類至分類上
            onDragEnterCategory(e, id) {
                if(this._d.currentDraggingCategoryId) {
                    if(this.isUneditableCategory(id)) return;
                    if(!this.isCurrentDraggingMediaIdsEmpty) return;

                    let element = this.findCategoryElementById(id);
                    this._d.currentDraggingOverCategoryId = id;
                    if(this.isCategoryDragSourceBefore(this._d.currentDraggingCategoryId, id)) {
                        this.insertAfter(this._d.categoryDraggingIndicator, element)
                    } else {
                        this.insertBefore(this._d.categoryDraggingIndicator, element)
                    }
                } else if(!this.isCurrentDraggingMediaIdsEmpty) {
                    if(!this.isAllCategory(id) && this._d.currentCategory != id) {
                        e.target.classList.add('on-drag');
                    }
                }
            },
            // dragleave事件，拖曳媒體出分類
            onDragLeaveCategory(e) {
                e.target.classList.remove('on-drag');
            },
            // dragend事件，放開拖曳媒體
            onDropMedia() {
                this.clearCurrentDraggingMediaIds();
            },
            // drop事件，拖曳媒體並drop至分類上
            onDropOnCategory(e, id) {
                e.target.classList.remove('on-drag');
                if(!this.isAllCategory(id) && this._d.currentCategory != id && !this.isCurrentDraggingMediaIdsEmpty) {
                    this.$root.$emit('update_category_for_medias', id, this._d.currentDraggingMediaIds);
                }
            },
            // 切換分類
            switchCategory(id) {
                if(this._d.currentEditingCategory) {
                    this.cancelCategoryEditing();
                }

                if(!this._d.fetchingLock && !this._d.currentEditingCategory) {
                    this.clearSelectedMedia();
                    this.clearCurrentSelectedMedia();
                    this._d.medias = [];
                    this._d.currentCategory = id;
                    this._d.lastFetchedMediaId = null;
                    this._d.fetchingEnd = false;
                    this.$root.$emit('fetch_medias', 35);
                    this.$root.$emit('remove_all_uploaded_files');
                }
            },
            // 減少分類的媒體數量
            substractCategoryCount(id, number, substractFromAll = true) {
                let category = this.findCategory(id);
                if(category) {
                    category.count -= number;
                }
                if(substractFromAll) {
                    let category = this.findCategory('all');
                    if(category) {
                        category.count -= number;
                    }
                }
            },
            // 增加分類的媒體數量
            addCategoryCount(id, number, addToAll = true) {
                let category = this.findCategory(id);
                if(category) {
                    category.count += number;
                }
                if(addToAll) {
                    let category = this.findCategory('all');
                    if(category) {
                        category.count += number;
                    }
                }
            },
            // click事件，編輯分類
            onEditCategory(id) {
                if(!this.isUneditableCategory(id)) {
                    this._d.currentEditingCategory = id;
                    this._d.currentEditingCategoryText = this.getCategoryName(id);
                }
            },
            // 從列表刪除分類
            deleteCategoryFromList(id) {
                this._d.categories = this._d.categories.filter(category => category.id != id);
                if(id == this._d.currentCategory) {
                    this._d.medias = [];
                    this._d.currentCategory = null;
                }
            },
            // click事件，刪除分類
            onDeleteCategory(id) {
                if(!this.isUneditableCategory(id) && id) {
                    if(confirm(this._d.text.deleteConfirmation)) {
                        this.$root.$emit('delete_category', id);
                    }
                }
            },
            // 取消分類編輯
            cancelCategoryEditing() {
                this._d.currentEditingCategory = null;
                this._d.currentEditingCategoryText = null;
            },
            // click事件，更新分類名稱
            onUpdateCategoryName() {
                this.$root.$emit('update_category_name', this._d.currentEditingCategory, this._d.currentEditingCategoryText)
            },
            // 更新分類名稱
            updateListCategoryName(id, name) {
                let category = this.findCategory(id);
                if(category) {
                    category.name = name;
                }
            },
            // click事件，取消新增分類
            onCancelCategoryAdding() {
                this._d.addingNewCategory = false;
            },
            // click事件，新增分類
            onAddCategory() {
                this.$root.$emit('add_category', this._d.currentEditingCategoryText);
            },
            // 新增分類至列表開頭
            addCategoryToList(id, name) {
                let _categories = [];
                _categories = _categories.concat(this._d.categories.filter(category => this.isUneditableCategory(category.id)))
                _categories.push({
                    id: id,
                    name: name,
                    count: 0,
                })
                _categories = _categories.concat(this._d.categories.filter(category => !this.isUneditableCategory(category.id)))
                this._d.categories = _categories;
            },
            // 從分類列表中找尋分類的element
            findCategoryElementById(id) {
                let element = document.querySelector('.category[data-id="' + id + '"]');
                return element;
            },
            // insert after
            insertAfter(newNode, referenceNode) {
                referenceNode.parentNode.appendChild(newNode);
                referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
            },
            // insert before
            insertBefore(newNode, referenceNode) {
                referenceNode.parentNode.appendChild(newNode);
                referenceNode.parentNode.insertBefore(newNode, referenceNode);
            },
            // 拖曳的分類比目的分類還前面
            isCategoryDragSourceBefore(sourceId, targetId) {
                let dragSourceIndex = 0, dragTargetIndex = 0;
                this._d.categories.forEach((category, index) => {
                    if(category.id == sourceId) {
                        dragSourceIndex = index;
                    }
                    if(category.id == targetId) {
                        dragTargetIndex = index;
                    }
                });
                return dragSourceIndex < dragTargetIndex;
            },
            // dragstart事件，拖曳分類
            onDragCategory(id) {
                this._d.currentDraggingCategoryId = id;

                let indicatorElement = document.createElement('span')
                indicatorElement.className = 'dragging-indicator';
                this._d.categoryDraggingIndicator = indicatorElement;
            },
            // 交換分類的順序
            switchCategoryOrder(draggingSourceId, draggingTargetId) {
                if(draggingSourceId == draggingTargetId) return;
                let _categories = [];
                let category = this.findCategory(draggingSourceId);
                let insertBefore = this.isCategoryDragSourceBefore(draggingSourceId, draggingTargetId);

                if(!insertBefore) {
                    this._d.categories.reverse();
                }

                this._d.categories.forEach((_category, index) => {
                    if(_category.id != category.id) {
                        _categories.push(_category)
                    }
                    if(_category.id == draggingTargetId) {
                        _categories.push(category);
                    }
                })

                if(!insertBefore) {
                    _categories.reverse();
                }
                this._d.categories = _categories
                this.$root.$emit('update_category_order',
                                _categories
                                    .filter(category => !this.isUneditableCategory(category.id))
                                    .map(category => category.id)
                                    .join(',')
                );
            },
            // dragend事件，拖曳分類並放置分類上
            onDropCategory() {
                let indicator = document.querySelector('.dragging-indicator')
                indicator.parentNode.removeChild(indicator);
                this.switchCategoryOrder(this._d.currentDraggingCategoryId, this._d.currentDraggingOverCategoryId);
                this._d.currentDraggingOverCategoryId = null;
                this._d.currentDraggingCategoryId = null;
            }
        }
    }
</script>

<style scoped>
</style>
