<!--
    The general idea here is that you define a context menu and then use the v-context-menu
    directive to assign it to an element and pass in optional context.

    The directive creates a handler for the element's contextmenu event and shows the appropriate
    context menu with the provided context.

    Here is what all of that looks like:

    // define the context menu

    <px-menu ref="mymenu" :items="[
        {
            id: 'copy',
            icon: iconUrl,
            label: 'Copy',

            // function with a single arg which will be the context from the directive
            handler: 'onContextMenuCopy',

            // visible / enabled can be a function or bool
            enabled: (ctx) => ctx.isSomething,
            visible: true
        },
        {
            id: 'copy',
            icon: iconUrl,
            label: 'Copy',

            // function with a single arg which will be the context from the directive
            handler: 'onContextMenuCopy',

            // visible / enabled can be a function or bool
            enabled: (ctx) => ctx.isSomething,
            visible: true
        },
        {
            isSeparator: true
        },
        {
            id: 'advanced',
            label: 'Advanced',
            items: [],
        },
    ]" />

    // use the context menu (no context)
    <div v-context-menu="'mymenu'" />

    // use the context menu (pass dynamic mydata as context)
    <div v-context-menu:[mydata]="'mymenu'" />


-->
<template>
    <px-float
        v-bind="{
            placement: 'right-start',
            ...floatProps,
        }"
        :popup-class="bem('popup')"
        ref="popup"
        variant="none"
        @hide="afterHide"
    >
        <div :class="bem()">
            <slot v-for="item in items" :item="item" :data="data" :done="hide">
                <PxMenuItem
                    :key="item.id"
                    :separator="item.separator"
                    :label="item.label"
                    :hint="item.hint"
                    :items="item.items"
                    :icon="item.icon"
                    :visible="item.visible"
                    :disabled="item.disabled"
                    :handler="item.handler"
                    :iconSize="calcIconSize"
                    :iconClass="iconClass"
                    :data="data"
                    @done="hide"
                    @iconsized="iconSized"
                />
            </slot>
        </div>
    </px-float>
</template>

<script>
import PxFloat from './PxFloat.vue';
import PxMenuItem from './PxMenuItem.vue';

// ================================================================================
// Component
// ================================================================================

const PxMenu = {
    name: 'px-menu',
    components: { PxFloat, PxMenuItem },
    mixins: [],
    emits: ['done'],
    props: {
        items: { type: Array, default: null },
        iconSize: { type: [String, Number], default: 1 },
        iconClass: { type: String, default: null },
        floatProps: { type: Object, default: null },
    },
    data() {
        return {
            data: null,
        };
    },
    computed: {
        calcIconSize() {
            if (this.items.find(item => !!item.icon)) {
                return this.iconSize;
            }
            return 0;
        },
    },
    methods: {
        showAtCursor(mouseEvent, data) {
            this.data = data;
            this.$refs.popup?.showAtCursor(mouseEvent);
        },
        show(data) {
            this.data = data;
            this.$refs.popup?.show();
        },
        hide() {
            this.$refs.popup?.hide();
        },
        afterHide() {
            this.data = null;
        },
        iconSized(e) {
            console.log(e);
        },
    },
};

// ================================================================================
// Directives
// ================================================================================

const createDirective = eventName => ({
    mounted(el, binding, vnode) {
        if (!binding || !vnode) {
            return;
        }

        binding.el = el;
        binding.contextMenuHandler = e => {
            e.preventDefault();
            e.stopPropagation();

            const name = binding?.value;
            const data = binding?.arg;
            const $refs = vnode?.ctx?.refs;

            if ($refs && name in $refs) {
                const menu = $refs[name];

                if (typeof menu?.show == 'function') {
                    menu.showAtCursor(e, data);
                }
            }
        };

        if (binding.el) {
            binding.el.addEventListener(eventName, binding.contextMenuHandler);
        }
    },
    unbind(el, binding) {
        if (binding.el) {
            binding.el.removeEventListener(eventName, binding.contextMenuHandler);
        }
    },
});

const contextMenuDirective = createDirective('contextmenu');
const clickDirective = createDirective('click');
const menuDirective = createDirective('click');

export {
    PxMenu as default,
    PxMenu,
    createDirective,
    contextMenuDirective,
    menuDirective,
    clickDirective,
};
</script>

<style lang="scss">
@use '../styles/px.scss' as *;
@use '@thinkpixellab-public/px-styles/src/modules/controls' as *;

.px-menu {
    font-family: get('font-family');
    background-color: site-var(page-bg);
    color: site-var(page-fg);
    border-radius: get('controls.border-radius');
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: stretch;

    &__popup {
        @include popup();
    }
}
</style>
