<template>
    <component v-if="!asChild" :is="as" :ref="setRef" :class="cx('root')" v-bind="attrs">
        <slot />
    </component>
    <slot v-else :a11yAttrs="a11yAttrs" :class="cx('root')" />
</template>

<script>
import { createMotion } from '@primeuix/motion';
import { isElement } from '@primeuix/utils/dom';
import { mergeProps } from 'vue';
import BaseSidebarMenuSub from './BaseSidebarMenuSub.vue';

export default {
    name: 'SidebarMenuSub',
    extends: BaseSidebarMenuSub,
    inheritAttrs: false,
    inject: {
        $pcSidebar: { default: null },
        $pcSidebarMenuItem: { default: null }
    },
    subEl: null,
    motion: null,
    mounted() {
        this.syncMotion(false);
    },
    beforeUnmount() {
        this.cancelMotion();
    },
    watch: {
        isCollapsible() {
            this.syncMotion(true);
        },
        isOpen() {
            this.syncMotion(true);
        }
    },
    methods: {
        setRef(el) {
            const resolved = isElement(el) ? el : (el?.$el ?? null);

            this.subEl = isElement(resolved) ? resolved : null;
        },
        ensureMotion() {
            if (!this.subEl) return null;

            if (!this.motion) {
                this.motion = createMotion(this.subEl, {
                    name: 'p-sidebar-menu-sub',
                    cssVarPrefix: 'px-sidebar-menu-sub',
                    autoHeight: true,
                    duration: 200
                });
            }

            return this.motion;
        },
        cancelMotion() {
            this.motion?.cancel();
            this.motion = null;
        },
        syncMotion(animate) {
            const el = this.subEl;

            if (typeof window === 'undefined' || !el) return;

            if (!this.isCollapsible) {
                this.cancelMotion();
                el.style.removeProperty('display');

                return;
            }

            const motion = this.ensureMotion();

            if (!motion) return;

            if (!animate) {
                if (this.isOpen) el.style.removeProperty('display');
                else el.style.display = 'none';

                return;
            }

            if (this.isOpen) {
                el.style.removeProperty('display');
                motion.enter();
            } else {
                motion.leave().then(() => {
                    if (this.isCollapsible && !this.isOpen && this.subEl) {
                        this.subEl.style.display = 'none';
                    }
                });
            }
        }
    },
    computed: {
        isCollapsible() {
            return !!this.$pcSidebarMenuItem?.collapsible;
        },
        isOpen() {
            return this.isCollapsible ? !!this.$pcSidebarMenuItem?.d_open : true;
        },
        a11yAttrs() {
            const sidebarPart = this.$pcSidebar?.getSectionAttrs('menusub') ?? {};

            return {
                ...sidebarPart,
                role: 'list',
                'data-pc-section': 'menusub'
            };
        },
        attrs() {
            return mergeProps(this.a11yAttrs, this.ptmi('root'));
        }
    }
};
</script>
