<template>
    <div>
        <h2 class="bm-admin__title">Structure</h2>

        <VueDraggable
            v-model="localInstances"
            :group="{ name: 'bm-structure' }"
            :animation="150"
            ghost-class="bm-structure__ghost"
            chosen-class="bm-structure__chosen"
            item-key="instance_id"
            handle=".bm-structure__handle"
            class="bm-structure"
        >
            <StructureNode
                v-for="instance in localInstances"
                :key="instance.instance_id"
                :instance="instance"
                :selected-id="selectedId"
                :depth="0"
                @select="(id) => $emit('select', id)"
                @delete="(id) => $emit('delete', id)"
                @children-input="onChildrenInput"
            />

            <p v-if="localInstances.length === 0" class="bm-rail-empty">
                No elements on the canvas yet.
            </p>
        </VueDraggable>
    </div>
</template>

<script>
import { VueDraggable } from 'vue-draggable-plus';
import StructureNode from './StructureNode.vue';
import { replaceChildren } from '../../helpers/instance-tree.js';

export default {
    name: 'StructureTree',
    components: { VueDraggable, StructureNode },
    props: {
        // v-model binding — parent passes `instances`.
        value: { type: Array, default: () => [] },
        selectedId: { type: String, default: null },
    },
    created() {
        // Drag-mutation buffer, mirroring BlockPreviewCanvas: a nested→nested
        // structure move fires two children-input events in one tick, so we key
        // them by container id and flush atomically to avoid dropping one.
        this._pendingTopLevel = null;
        this._pendingChildUpdates = {};
        this._flushPending = false;
    },
    computed: {
        localInstances: {
            get() { return this.value; },
            set(next) {
                this._pendingTopLevel = next;
                this.scheduleFlush();
            },
        },
    },
    methods: {
        onChildrenInput(containerId, newChildren) {
            this._pendingChildUpdates[containerId] = newChildren;
            this.scheduleFlush();
        },
        scheduleFlush() {
            if (this._flushPending) return;
            this._flushPending = true;
            this.$nextTick(() => {
                this._flushPending = false;
                let result = this._pendingTopLevel !== null ? this._pendingTopLevel : this.value;
                for (const [containerId, children] of Object.entries(this._pendingChildUpdates)) {
                    result = replaceChildren(result, containerId, children);
                }
                this._pendingTopLevel = null;
                this._pendingChildUpdates = {};
                this.$emit('input', result);
            });
        },
    },
};
</script>
