/**
 * Enhanced Drag and Drop for GLANCE LED Panel Developer Platform
 * This script implements improved drag-and-drop functionality for the no-code interface.
 */

document.addEventListener('DOMContentLoaded', function() {
    // Only initialize in no-code mode
    if (document.body.getAttribute('data-mode') !== 'no-code') return;
    
    console.log("Initializing Enhanced Drag and Drop...");
    initDragDrop();
});

/**
 * Initialize drag and drop functionality
 */
function initDragDrop() {
    
    // Setup workflow block reordering
    setupWorkflowReordering();

}

/**
 * Setup drag from library to workflow
 */
function setupLibraryDragDrop() {
    const blockItems = document.querySelectorAll('.block-item');
    const workflowArea = document.querySelector('.workflow-area');
    
    if (!blockItems.length || !workflowArea) {
        console.error("Block items or workflow area not found");
        return;
    }
    
    // Make library blocks draggable with visual feedback
    blockItems.forEach(item => {
        item.setAttribute('draggable', 'true');
        
        item.addEventListener('dragstart', (e) => {
            const blockType = item.getAttribute('data-block-type');
            e.dataTransfer.setData('application/block-type', blockType);
            e.dataTransfer.effectAllowed = 'copy';
            
            item.classList.add('dragging-from-library');
            
            // Create custom drag image to improve drag visual
            const ghostElement = item.cloneNode(true);
            ghostElement.style.position = 'absolute';
            ghostElement.style.top = '-1000px';
            ghostElement.style.opacity = '0.8';
            document.body.appendChild(ghostElement);
            e.dataTransfer.setDragImage(ghostElement, 30, 30);
            
            // Remove ghost after a short delay
            setTimeout(() => {
                document.body.removeChild(ghostElement);
            }, 100);
        });
        
        item.addEventListener('dragend', () => {
            item.classList.remove('dragging-from-library');
        });
    });
    
    // Make workflow area a drop target
    workflowArea.addEventListener('dragover', (e) => {
        e.preventDefault();
        
        // Check if we're dragging from library or within workflow
        const isFromLibrary = e.dataTransfer.types.includes('application/block-type');
        
        if (isFromLibrary) {
            e.dataTransfer.dropEffect = 'copy';
            workflowArea.classList.add('library-drag-over');
        }
    });
    
    workflowArea.addEventListener('dragleave', (e) => {
        // Only remove highlight when actually leaving the container
        const rect = workflowArea.getBoundingClientRect();
        const isOutside = 
            e.clientX <= rect.left ||
            e.clientX >= rect.right ||
            e.clientY <= rect.top ||
            e.clientY >= rect.bottom;
            
        if (isOutside) {
            workflowArea.classList.remove('library-drag-over');
        }
    });
    
    workflowArea.addEventListener('drop', (e) => {
        e.preventDefault();
        workflowArea.classList.remove('library-drag-over');
        
        // Handle drop from library
        const blockType = e.dataTransfer.getData('application/block-type');
        if (blockType && window.blockManager) {
            // Get default properties for this block type
            const properties = getDefaultProperties(blockType);
            
            // Add block to workflow
            window.blockManager.addBlock({
                type: blockType,
                properties: properties
            });
            
            // Update preview if auto-preview is enabled
            if (window.autoPreviewEnabled) {
                window.updatePreview();
            }
        }
    });
}

/**
 * Setup reordering blocks within the workflow
 */
function setupWorkflowReordering() {
    const workflowArea = document.querySelector('.workflow-area');
    if (!workflowArea) return;
    
    // Use event delegation for dynamically added blocks
    workflowArea.addEventListener('dragstart', (e) => {
        const workflowBlock = e.target.closest('.workflow-block');
        if (!workflowBlock) return;
        
        e.dataTransfer.setData('application/block-id', workflowBlock.id);
        e.dataTransfer.effectAllowed = 'move';
        
        workflowBlock.classList.add('dragging-within-workflow');
        
        // Delay adding opacity to make drag image normal
        setTimeout(() => {
            workflowBlock.style.opacity = '0.4';
        }, 0);
    });
    
    workflowArea.addEventListener('dragend', (e) => {
        const workflowBlock = e.target.closest('.workflow-block');
        if (!workflowBlock) return;
        
        workflowBlock.classList.remove('dragging-within-workflow');
        workflowBlock.style.opacity = '1';
        
        // Remove all drop indicators
        document.querySelectorAll('.block-drop-indicator').forEach(el => el.remove());
        workflowArea.classList.remove('workflow-drag-over');
    });
    
    workflowArea.addEventListener('dragover', (e) => {
        e.preventDefault();
        
        // Check if we're reordering workflow blocks
        const isReordering = e.dataTransfer.types.includes('application/block-id');
        
        if (isReordering) {
            e.dataTransfer.dropEffect = 'move';
            workflowArea.classList.add('workflow-drag-over');
            
            // Find the block being dragged
            const draggingBlock = document.querySelector('.dragging-within-workflow');
            if (!draggingBlock) return;
            
            // Find the block we're dragging over
            const afterElement = getDragAfterElement(workflowArea, e.clientY);
            
            // Remove existing drop indicators
            document.querySelectorAll('.block-drop-indicator').forEach(el => el.remove());
            
            // Create a drop indicator
            const dropIndicator = document.createElement('div');
            dropIndicator.className = 'block-drop-indicator';
            
            if (afterElement) {
                workflowArea.insertBefore(dropIndicator, afterElement);
            } else {
                workflowArea.appendChild(dropIndicator);
            }
        }
    });
    
    workflowArea.addEventListener('drop', (e) => {
        e.preventDefault();
        workflowArea.classList.remove('workflow-drag-over');
        
        // Remove drop indicators
        document.querySelectorAll('.block-drop-indicator').forEach(el => el.remove());
        
        // Handle reordering drop
        const blockId = e.dataTransfer.getData('application/block-id');
        if (blockId && window.blockManager) {
            const blockIndex = window.blockManager.blocks.findIndex(block => block.id === blockId);
            if (blockIndex === -1) return;
            
            // Find where to drop it
            const afterElement = getDragAfterElement(workflowArea, e.clientY);
            
            // Calculate new index
            let newIndex;
            if (afterElement) {
                const afterBlockId = afterElement.id;
                const afterBlockIndex = window.blockManager.blocks.findIndex(block => block.id === afterBlockId);
                
                newIndex = afterBlockIndex;
                // If dropping below the current position, adjust index
                if (blockIndex < afterBlockIndex) {
                    newIndex--;
                }
            } else {
                // If dropping at the end
                newIndex = window.blockManager.blocks.length - 1;
            }
            
            // Don't reorder if the index is the same or invalid
            if (newIndex === blockIndex || newIndex < 0 || newIndex >= window.blockManager.blocks.length) {
                return;
            }
            
            // Reorder blocks
            const [movedBlock] = window.blockManager.blocks.splice(blockIndex, 1);
            window.blockManager.blocks.splice(newIndex, 0, movedBlock);
            
            // Re-render workflow
            window.blockManager.renderWorkflow();
            
            // Update preview if auto-preview is enabled
            if (window.autoPreviewEnabled) {
                window.updatePreview();
            }
        }
    });
}

/**
 * Get default properties for a new block from library
 */
function getDefaultProperties(blockType) {
    // Get canvas dimensions for calculating default positions
    const canvasSize = document.body.getAttribute('data-canvas-size') || '64x32';
    const [canvasWidth, canvasHeight] = canvasSize.split('x').map(Number);
    
    switch(blockType) {
        case 'drawText':
            return {
                text: 'GLANCE',
                x: 5,
                y: 10,
                color: '#00FF00',
                font: 'bitmap_5x7',
                alignment: 'left'
            };
            
        case 'setPixel':
            return {
                x: Math.floor(canvasWidth / 2),
                y: Math.floor(canvasHeight / 2),
                color: '#FFFFFF'
            };
            
        case 'getData':
            return {
                url: 'https://api.example.com/data',
                apiKey: '',
                variable: 'data'
            };
            
        default:
            return {};
    }
}

/**
 * Helper function to determine where to drop when reordering
 */
function getDragAfterElement(container, y) {
    // Get all non-dragging blocks
    const draggableElements = [...container.querySelectorAll('.workflow-block:not(.dragging-within-workflow)')];
    
    // Find the first element that's below the cursor
    return draggableElements.reduce((closest, child) => {
        const box = child.getBoundingClientRect();
        const offset = y - box.top - box.height / 2;
        
        if (offset < 0 && offset > closest.offset) {
            return { offset: offset, element: child };
        } else {
            return closest;
        }
    }, { offset: Number.NEGATIVE_INFINITY }).element;
}


/**
 * Make sure entire block rows are draggable, not just the handle
 */
function enhanceBlockDraggability() {
    // Find all workflow blocks
    const workflowBlocks = document.querySelectorAll('.workflow-block');
    
    workflowBlocks.forEach(block => {
        // Make the entire block draggable
        block.setAttribute('draggable', 'true');
        
        // Add clear visual feedback for draggable elements
        block.addEventListener('mouseenter', () => {
            block.style.cursor = 'grab';
        });
        
        block.addEventListener('mouseleave', () => {
            block.style.cursor = '';
        });
        
        // Change cursor on mousedown
        block.addEventListener('mousedown', () => {
            block.style.cursor = 'grabbing';
        });
        
        block.addEventListener('mouseup', () => {
            block.style.cursor = 'grab';
        });
    });
}

// Set up a mutation observer to enhance newly added blocks
function setupMutationObserver() {
    const workflowArea = document.querySelector('.workflow-area');
    if (!workflowArea) return;
    
    // Create an observer to watch for new blocks
    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                // Check if any added nodes are workflow blocks
                mutation.addedNodes.forEach(node => {
                    if (node.classList && node.classList.contains('workflow-block')) {
                        // Make the new block draggable
                        node.setAttribute('draggable', 'true');
                        
                        // Add hover cursor effect
                        node.addEventListener('mouseenter', () => {
                            node.style.cursor = 'grab';
                        });
                        
                        node.addEventListener('mouseleave', () => {
                            node.style.cursor = '';
                        });
                    }
                });
            }
        });
    });
    
    // Start observing
    observer.observe(workflowArea, { childList: true });
}

// Run once the DOM is fully loaded
document.addEventListener('DOMContentLoaded', function() {
    // Apply these enhancements after a short delay to ensure all blocks are loaded
    setTimeout(() => {
        enhanceBlockDraggability();
        setupMutationObserver();
    }, 1000);
});
