<template>
    <div>
        <h2 class="bm-admin__title">Elements</h2>
        <p class="bm-picker__hint">Click to append, or drag onto the canvas.</p>

        <div v-if="loading">Loading…</div>
        <div v-else-if="elements.length === 0">No elements found.</div>

        <div v-else>
            <div v-for="category in categories" :key="category" class="bm-picker__group">
                <h3 class="bm-picker__group-label">{{ category }}</h3>
                <VueDraggable
                    v-model="groupArrays[category]"
                    :group="{ name: 'bm-elements', pull: 'clone', put: false }"
                    :sort="false"
                    :clone="elementClone"
                    :force-fallback="true"
                    :fallback-on-body="true"
                    item-key="type"
                    class="bm-picker__draggable"
                >
                    <div
                        v-for="element in groupArrays[category]"
                        :key="element.type"
                        class="bm-picker__tile"
                        :class="{ 'bm-picker__tile--container': element.accepts_children }"
                        role="button"
                        tabindex="0"
                        @click="$emit('add', element)"
                        @keydown.enter.prevent="$emit('add', element)"
                        @keydown.space.prevent="$emit('add', element)"
                    >
                        <span>{{ element.label }}</span>
                        <span v-if="element.accepts_children" class="bm-picker__tile-badge">Layout</span>
                    </div>
                </VueDraggable>
            </div>
        </div>
    </div>
</template>

<script>
import { VueDraggable } from 'vue-draggable-plus';

let dropSequence = 0;

export default {
    name: 'ElementPicker',
    components: { VueDraggable },
    props: {
        elements: { type: Array, required: true },
        loading: { type: Boolean, default: false },
    },
    data() {
        return {
            // Per-category writable copies. The lists are never mutated in
            // practice (pull:'clone' + put:false + sort:false) — they exist
            // only because VueDraggable's v-model requires a writable target.
            groupArrays: {},
        };
    },
    computed: {
        categories() {
            return Object.keys(this.groupArrays);
        },
    },
    watch: {
        elements: { immediate: true, handler() { this.rebuildGroups(); } },
    },
    methods: {
        rebuildGroups() {
            const next = {};
            for (const el of this.elements) {
                const key = el.category || 'other';
                if (!next[key]) next[key] = [];
                next[key].push(el);
            }
            this.groupArrays = next;
        },
        /**
         * Converts a picker manifest into a canvas instance. Called by Sortable
         * for each drop. Matches the shape produced by BlockManagerMain.addInstance
         * so click-to-add and drag-to-add are indistinguishable downstream.
         */
        elementClone(manifest) {
            dropSequence += 1;
            const instance = {
                instance_id: `el-${Date.now()}-${dropSequence}`,
                element_type: manifest.type,
                variant: manifest.default_variant,
                field_name: manifest.type,
            };
            if (manifest.accepts_children) {
                instance.children = [];
                instance.style_props = { base: { default: {} } };
            }
            return instance;
        },
    },
};
</script>
