<template>
    <div id="my-container">
        <div
            v-if="item.header && !isItemHidden"
            class="vsm--header"
            :class="item.class"
            v-bind="item.attributes"
        >
            {{ item.title }} <b-icon icon="pie-chart-fill"></b-icon>
        </div>
        <div
            v-else-if="!isItemHidden"
            class="vsm--item"
            :class="[{ 'vsm--item_open': show }]"
            @mouseover="mouseOverEvent"
            @mouseout="mouseOutEvent"
        >
            <custom-sidebar-menu-link
                :item="item"
                :class="itemLinkClass"
                :attributes="item.attributes"
                @click.native="clickEvent"
            >
                <custom-sidebar-menu-icon
                    v-if="item.icon && !isMobileItem"
                    :icon="item.icon"
                />
                <transition name="fade-animation" :appear="isMobileItem">
                    <template
                        v-if="
                            (isCollapsed && !isFirstLevel) ||
                                !isCollapsed ||
                                isMobileItem
                        "
                    >
                        <span class="vsm--title">
                            <custom-tooltip :data="item"></custom-tooltip>
                            <b-icon
                                v-if="item.sortable"
                                :icon="item.sortIcon"
                                @click="onClickSortSettings"
                            ></b-icon>
                        </span>
                    </template>
                </transition>
                <template
                    v-if="
                        (isCollapsed && !isFirstLevel) ||
                            !isCollapsed ||
                            isMobileItem
                    "
                >
                    <sidebar-menu-badge v-if="item.badge" :badge="item.badge" />
                    <div
                        v-if="itemHasChild"
                        class="vsm--arrow"
                        :class="[
                            { 'vsm--arrow_open': show },
                            { 'vsm--arrow_slot': $slots['dropdown-icon'] },
                        ]"
                    >
                        <slot name="dropdown-icon" />
                    </div>
                </template>
            </custom-sidebar-menu-link>

            <template v-if="itemHasChild">
                <template
                    v-if="
                        (isCollapsed && !isFirstLevel) ||
                            !isCollapsed ||
                            isMobileItem
                    "
                >
                    <transition
                        :appear="isMobileItem"
                        name="expand"
                        @enter="expandEnter"
                        @afterEnter="expandAfterEnter"
                        @beforeLeave="expandBeforeLeave"
                    >
                        <div
                            v-if="show"
                            class="vsm--dropdown"
                            :class="isMobileItem && 'vsm--dropdown_mobile-item'"
                            :style="isMobileItem && mobileItemStyle.dropdown"
                        >
                            <div class="vsm--list">
                                <custom-sidebar-menu-item
                                    v-for="(subItem, index) in item.child"
                                    :key="index"
                                    :item="subItem"
                                    :level="level + 1"
                                    :show-child="showChild"
                                    :rtl="rtl"
                                    :is-collapsed="isCollapsed"
                                >
                                    <slot
                                        slot="dropdown-icon"
                                        name="dropdown-icon"
                                    />
                                </custom-sidebar-menu-item>
                            </div>
                        </div>
                    </transition>
                </template>
            </template>

            <b-modal
                ref="modal"
                v-if="item.sortable"
                id="my-modal"
                static
                title="Custom Case List Order"
            >
                <draggable
                    :list="item.child"
                    :disabled="!enabled"
                    class="list-group"
                    ghost-class="ghost"
                    @end="checkMove"
                    @start="dragging = true"
                    handle=".handle"
                >
                    <div
                        class="list-group-item"
                        v-for="element in item.child"
                        :key="element.title"
                    >
                        <b-row>
                            <b-col
                                ><b-icon icon="check-circle"></b-icon>
                            </b-col>
                            <b-col cols="9">{{ element.title }}</b-col>
                            <b-col
                                ><i class="fa fa-align-justify handle"></i
                            ></b-col>
                        </b-row>
                    </div>
                </draggable>

                <template #modal-footer="{ cancel }">
                    <b-button size="sm" variant="danger" @click="cancel()">
                        Cancel
                    </b-button>
                </template>
            </b-modal>
        </div>
    </div>
</template>

<script>
import draggable from "vuedraggable";
import CustomSidebarMenuLink from "./CustomSidebarMenuLink";
import CustomSidebarMenuIcon from "./CustomSidebarMenuIcon";
import CustomTooltip from "./../utils/CustomTooltip.vue";

export default {
    name: "CustomSidebarMenuItem",
    props: {
        item: {
            type: Object,
            required: true,
        },
        level: {
            type: Number,
            default: 1,
        },
        isMobileItem: {
            type: Boolean,
            default: false,
        },
        mobileItem: {
            type: Object,
            default: null,
        },
        activeShow: {
            type: Object,
            default: null,
        },
        showChild: {
            type: Boolean,
            default: false,
        },
        showOneChild: {
            type: Boolean,
            default: false,
        },
        rtl: {
            type: Boolean,
            default: false,
        },
        disableHover: {
            type: Boolean,
            default: false,
        },
        mobileItemStyle: {
            type: Object,
            default: null,
        },
    },
    components: {
        draggable,
        CustomSidebarMenuLink,
        CustomSidebarMenuIcon,
        CustomTooltip
    },
    data() {
        return {
            enabled: true,
            dragging: false,
            itemShow: false,
            itemHover: false,
            exactActive: false,
            active: false,
            titleHover: '',
        };
    },
    computed: {
        isCollapsed() {
            return this.$parent.isCollapsed;
        },
        itemLinkClass() {
            return [
                "vsm--link",
                !this.isMobileItem ? `vsm--link_level-${this.level}` : "",
                { "vsm--link_mobile-item": this.isMobileItem },
                { "vsm--link_hover": this.hover },
                { "vsm--link_active": this.active },
                { "vsm--link_exact-active": this.exactActive },
                { "vsm--link_disabled": this.item.disabled },
                this.item.class,
            ];
        },
        draggingInfo() {
            return this.dragging ? "under drag" : "";
        },
        show: {
            get() {
                if (!this.itemHasChild) return false;
                if (this.showChild || this.isMobileItem) return true;
                return this.itemShow;
            },
            set(show) {
                if (this.showOneChild) {
                    show
                        ? this.emitActiveShow(this.item)
                        : this.emitActiveShow(null);
                }
                this.itemShow = show;
            },
        },
        isFirstLevel() {
            return this.level === 1;
        },
        itemHasChild() {
            return !!(this.item.child && this.item.child.length > 0);
        },
        isItemHidden() {
            return false;
        },
    },
    watch: {
        $route() {
            setTimeout(() => {
                if (this.item.header || this.item.component) return;
                this.initState();
            }, 1);
        },
        item(newItem, item) {
            this.emitItemUpdate(newItem, item);
        },
        activeShow() {
            this.itemShow = this.item === this.activeShow;
        },
    },
    created() {
        this.initState();
    },
    methods: {
        /**
         * Match the route to ensure the correct location
         * @param {string} href
         * @param {string} exactPath
         * @return {boolean}
         */
        matchRoute({ href, exactPath }) {
            if (!href) return false;
            if (this.$router) {
                const { route } = this.$router.resolve(href);
                return exactPath
                    ? route.path === this.$route.path
                    : this.matchExactRoute(href);
            } else {
                return exactPath
                    ? href === window.location.pathname
                    : this.matchExactRoute(href);
            }
        },
        /**
         * Match the exact route with the current location
         * @param {string} href
         * @return {boolean}
         */
        matchExactRoute(href) {
            if (!href) return false;
            if (this.$router) {
                const { route } = this.$router.resolve(href);
                return route.fullPath === this.$route.fullPath;
            } else {
                return (
                    href ===
                    window.location.pathname +
                        window.location.search +
                        window.location.hash
                );
            }
        },
        /**
         * Check if the child is active
         * @param {object} child
         * @return {boolean}
         */
        isChildActive(child) {
            if (!child) return false;
            return child.some((item) => {
                return this.isLinkActive(item);
            });
        },
        /**
         * Validate if the Alias is active
         * @param {object} item
         * @return {boobleam}
         */
        isAliasActive(item) {
            if (item.alias) {
                const current = this.$router
                    ? this.$route.fullPath
                    : window.location.pathname +
                      window.location.search +
                      window.location.hash;
                if (Array.isArray(item.alias)) {
                    return item.alias.some((alias) => {
                        return pathToRegexp(alias).test(current);
                    });
                } else {
                    return pathToRegexp(item.alias).test(current);
                }
            }
            return false;
        },
        /**
         * Validate if the link is active
         * @param {object} item
         * @return {boolean}
         */
        isLinkActive(item) {
            return (
                this.matchRoute(item) ||
                this.isChildActive(item.child) ||
                this.isAliasActive(item)
            );
        },
        /**
         * Ensurre if the link exact is active 
         * @param {object} item
         * @return {boolean}
         */
        isLinkExactActive(item) {
            return this.matchExactRoute(item.href);
        },
        /**
         * Initialize the state of the menu item
         */
        initState() {
            this.initActiveState();
            this.initShowState();
        },
        /**
         * Initalize the active state of the menu item
         */
        initActiveState() {
            this.active = this.isLinkActive(this.item);
            this.exactActive = this.isLinkExactActive(this.item);
        },
        /**
         * Initialize and show active state menu item 
         */
        initShowState() {
            if (!this.itemHasChild || this.showChild) return;
            if (
                (this.showOneChild && this.active && !this.show) ||
                (this.active && !this.show)
            ) {
                this.show = true;
            } else if (this.showOneChild && !this.active && this.show) {
                this.show = false;
            }
        },
        /**
         * Handler to check if the item is moving
         * @param {object} e
         */
        checkMove: function(e) {
            let aux = this.item.child.splice(e.newIndex, 1);
            this.item.child.splice(e.newIndex, 0, aux[0]);
        },
        /**
         * Click event Handler 
         * @param {object} event
         */
        clickEvent(event) {
            if (this.item.disabled) return;
            if (!this.item.href) {
                event.preventDefault();
            }
            this.emitItemClick(event, this.item, this);
            this.emitMobileItem(event, event.currentTarget.offsetParent);
            if (!this.itemHasChild || this.showChild || this.isMobileItem)
                return;
            if (!this.item.href || this.exactActive) {
                this.show = !this.show;
            }
        },
        /**
         * Mouse over event handler
         * @param {object} event
         */
        mouseOverEvent(event) {
            if (this.item.disabled) return;
            event.stopPropagation();
            this.itemHover = true;
            if (!this.disableHover) {
                this.emitMobileItem(event, event.currentTarget);
            }
        },
        /**
         * Mouse out event handler
         * @param {object} event
         */
        mouseOutEvent(event) {
            event.stopPropagation();
            this.itemHover = false;
        },
        /**
         * Expand sidebar menu item handler
         * @param {object} el
         */
        expandEnter(el) {
            el.style.height = el.scrollHeight + "px";
        },
        /**
         * Expand after enter menu item handler
         * @param {object} el
         */
        expandAfterEnter(el) {
            el.style.height = "auto";
        },
        /**
         * Expand before leace handler
         * @param {object} el
         */
        expandBeforeLeave(el) {
            if (this.isCollapsed && this.isFirstLevel) {
                el.style.display = "none";
                return;
            }
            el.style.height = el.scrollHeight + "px";
        },
        /**
         * Emit Mobile item handler
         * @param {object} event
         * @param {object} itemEl
         */
        emitMobileItem(event, itemEl) {
            if (this.hover) return;
            if (!this.isCollapsed || !this.isFirstLevel || this.isMobileItem)
                return;
            this.$emit("unset-mobile-item", true);
            setTimeout(() => {
                if (this.mobileItem !== this.item) {
                    this.$emit("set-mobile-item", { item: this.item, itemEl });
                }
                if (event.type === "click" && !this.itemHasChild) {
                    this.$emit("unset-mobile-item", false);
                }
            }, 0);
        },
        /**
         * Click Sort settings event handler
         * @param {object} event
         */
        onClickSortSettings(event) {
            event.preventDefault();
            event.stopPropagation();
            this.$refs["modal"].show();
        },
    },
    inject: ["emitActiveShow", "emitItemClick", "emitItemUpdate"],
};
</script>
