<template>
    <div ref="contextMenu"
         v-if="menuVisible"
         v-bind:style="menuStyle"
         v-on:blur="closeMenu"
         class="fm-context-menu"
         tabindex="-1">
        <ul v-for="(group, index) in menu"
            v-bind:key="`g-${index}`"
            class="list-unstyled">
            <li v-for="(item, index) in group"
                v-bind:key="`i-${index}`"
                v-if="showMenuItem(item.name)"
                v-on:click="menuAction(item.name)">
                <i class="fa-fw"
                   v-bind:class="item.icon"></i>
                {{ lang.contextMenu[item.name] }}
            </li>
        </ul>
    </div>
</template>

<script>
/* eslint-disable no-param-reassign */
import EventBus from './../../eventBus';
import translate from '../../mixins/translate';
import contextMenu from './mixins/contextMenu';
import contextMenuRules from './mixins/contextMenuRules';
import contextMenuActions from './mixins/contextMenuActions';

export default {
    name: 'ContextMenu',
    mixins: [translate, contextMenu, contextMenuRules, contextMenuActions],
    data() {
        return {
            menuVisible: false,
            menuStyle: {
                top: 0,
                left: 0,
            },
        };
    },
    mounted() {
        /**
         * Listen events
         * 'contextMenu'
         */
        EventBus.$on('contextMenu', event => this.showMenu(event));
    },
    computed: {
        /**
         * Context menu items
         * @returns {*}
         */
        menu() {
            return this.$store.state.fm.settings.contextMenu;
        },
    },
    methods: {
        /**
         * Show context menu
         * @param event
         */
        showMenu(event) {
            if (this.selectedItems) {
                this.menuVisible = true;

                // focus on menu
                this.$nextTick(() => {
                    if (this.$refs.contextMenu) {
                        this.$refs.contextMenu.focus();
                    }
                    // set menu params
                    this.setMenu(event.pageY, event.pageX);
                });
            }
        },

        /**
         * Set context menu coordinates
         * @param top
         * @param left
         */
        setMenu(top, left) {
            try {
                // get parent el (.fm-body)
                const el = this.$refs.contextMenu.parentNode;

                // get parent el size
                const elSize = el.getBoundingClientRect();

                // actual coordinates of the block
                const elY = window.pageYOffset + elSize.top;
                const elX = window.pageXOffset + elSize.left;

                // calculate the preliminary coordinates
                let menuY = top - elY;
                let menuX = left - elX;

                // calculate max X and Y coordinates
                const maxY = elY + (el.offsetHeight - this.$refs.contextMenu.offsetHeight - 25);
                const maxX = elX + (el.offsetWidth - this.$refs.contextMenu.offsetWidth - 25);

                if (top > maxY) menuY = maxY - elY;
                if (left > maxX) menuX = maxX - elX;

                // set coordinates
                this.menuStyle.top = `${menuY}px`;
                this.menuStyle.left = `${menuX}px`;
            } catch {
                // do nothing
            }
        },

        /**
         * Close context menu
         */
        closeMenu() {
            this.menuVisible = false;
        },

        /**
         * Show context menu item
         * @param name
         * @returns {*}
         */
        showMenuItem(name) {
            if (Object.prototype.hasOwnProperty.call(this, `${name}Rule`)) {
                return this[`${name}Rule`]();
            }

            return false;
        },

        /**
         * Call actions when clicking the context menu
         * @param name
         */
        menuAction(name) {
            if (Object.prototype.hasOwnProperty.call(this, `${name}Action`)) {
                this[`${name}Action`]();
            }
            // close context menu
            this.closeMenu();
        },
    },
};
</script>