<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Futuristic Binary Tree Visualizer</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.47/vue.global.prod.min.js"></script>
    <style>
        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        body {
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
            color: #fff;
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        #app {
            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 20px;
            box-sizing: border-box;
        }
        h1 {
            color: #fff;
            text-align: center;
            margin-bottom: 20px;
            font-size: 2.5em;
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
        }
        .controls {
            display: flex;
            gap: 15px;
            margin-bottom: 20px;
            width: 100%;
            max-width: 600px;
        }
        input, button {
            font-size: 18px;
            padding: 12px 20px;
            border: none;
            border-radius: 8px;
        }
        input {
            flex-grow: 1;
            background-color: rgba(255, 255, 255, 0.2);
            color: #fff;
            transition: background-color 0.3s;
        }
        input::placeholder {
            color: rgba(255, 255, 255, 0.6);
        }
        input:focus {
            background-color: rgba(255, 255, 255, 0.3);
            outline: none;
        }
        button {
            background: linear-gradient(45deg, #3498db, #2980b9);
            color: white;
            cursor: pointer;
            transition: all 0.3s;
            position: relative;
            overflow: hidden;
        }
        button:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        }
        button::after {
            content: '';
            position: absolute;
            top: -50%;
            left: -50%;
            width: 200%;
            height: 200%;
            background: rgba(255, 255, 255, 0.1);
            transform: rotate(45deg);
            transition: all 0.3s;
        }
        button:hover::after {
            top: -100%;
            left: -100%;
        }
        canvas {
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
            max-width: 100%;
            max-height: calc(100% - 150px);
        }
        .instructions {
            margin-top: 20px;
            color: rgba(255, 255, 255, 0.8);
            font-size: 14px;
            line-height: 1.6;
            text-align: center;
            max-width: 600px;
        }
    </style>
</head>
<body>
    <div id="app">
        <h1>Futuristic Binary Tree Visualizer</h1>
        <div class="controls">
            <input v-model="treeInput" placeholder="Enter tree values (e.g., 1,null,2,3)">
            <button @click="generateTree">Generate</button>
        </div>
        <canvas ref="canvas" @mousemove="onMouseMove" @mousedown="onMouseDown" @mouseup="onMouseUp"></canvas>
        <div class="instructions">
            <p>Drag nodes to reposition. Press 'Delete' key to remove a selected node. Hover over nodes and edges to see interactive effects. Drag a node close to another to make it a child.</p>
        </div>
    </div>

    <script>
        const { createApp, ref, onMounted, watch } = Vue;

        class TreeNode {
            constructor(val = 0, left = null, right = null) {
                this.val = val;
                this.left = left;
                this.right = right;
                this.x = 0;
                this.y = 0;
                this.targetX = 0;
                this.targetY = 0;
            }
        }

        createApp({
            setup() {
                const canvas = ref(null);
                const ctx = ref(null);
                const treeInput = ref('1,null,2,null,3,null,4,null,5,null,6');
                const root = ref(null);
                const selectedNode = ref(null);
                const hoveredNode = ref(null);
                const hoveredEdge = ref(null);
                const potentialParent = ref(null);
                const nodeRadius = ref(25);
                const animationSpeed = 0.1;
                const minNodeDistance = ref(100);

                const buildTree = (values) => {
                    if (!values || values.length === 0) return null;
                    const nodes = values.map(val => val === 'null' ? null : new TreeNode(parseInt(val)));
                    for (let i = 0; i < nodes.length; i++) {
                        if (nodes[i] !== null) {
                            const leftIndex = 2 * i + 1;
                            const rightIndex = 2 * i + 2;
                            if (leftIndex < nodes.length) nodes[i].left = nodes[leftIndex];
                            if (rightIndex < nodes.length) nodes[i].right = nodes[rightIndex];
                        }
                    }
                    return nodes[0];
                };

                const layoutTree = (node, depth = 0, left = 0, right = canvas.value.width) => {
                    if (!node) return;
                    const x = (left + right) / 2;
                    const y = depth * minNodeDistance.value + nodeRadius.value * 2;
                    node.targetX = x;
                    node.targetY = y;
                    if (node.x === 0 && node.y === 0) {
                        node.x = node.targetX;
                        node.y = node.targetY;
                    }
                    const childSpacing = Math.max((right - left) / 2, minNodeDistance.value);
                    layoutTree(node.left, depth + 1, left, x);
                    layoutTree(node.right, depth + 1, x, right);
                };

                const drawTree = () => {
                    if (!ctx.value) return;
                    ctx.value.clearRect(0, 0, canvas.value.width, canvas.value.height);
                    if (root.value) drawNode(root.value);
                };

                const drawNode = (node) => {
                    if (!node) return;

                    // Draw edges
                    if (node.left) drawEdge(node, node.left);
                    if (node.right) drawEdge(node, node.right);

                    // Draw node
                    ctx.value.beginPath();
                    ctx.value.arc(node.x, node.y, nodeRadius.value, 0, 2 * Math.PI);
                    const gradient = ctx.value.createRadialGradient(node.x, node.y, 0, node.x, node.y, nodeRadius.value);
                    if (node === selectedNode.value) {
                        gradient.addColorStop(0, '#e74c3c');
                        gradient.addColorStop(1, '#c0392b');
                    } else if (node === hoveredNode.value) {
                        gradient.addColorStop(0, '#3498db');
                        gradient.addColorStop(1, '#2980b9');
                    } else {
                        gradient.addColorStop(0, '#2ecc71');
                        gradient.addColorStop(1, '#27ae60');
                    }
                    ctx.value.fillStyle = gradient;
                    ctx.value.fill();
                    ctx.value.strokeStyle = '#fff';
                    ctx.value.lineWidth = 2;
                    ctx.value.stroke();

                    // Draw value
                    ctx.value.fillStyle = 'white';
                    ctx.value.font = `bold ${nodeRadius.value * 0.7}px Arial`;
                    ctx.value.textAlign = 'center';
                    ctx.value.textBaseline = 'middle';
                    ctx.value.fillText(node.val, node.x, node.y);

                    // Draw glow effect for potential parent
                    if (potentialParent.value === node) {
                        ctx.value.beginPath();
                        ctx.value.arc(node.x, node.y, nodeRadius.value + 10, 0, 2 * Math.PI);
                        ctx.value.strokeStyle = 'rgba(52, 152, 219, 0.5)';
                        ctx.value.lineWidth = 5;
                        ctx.value.stroke();
                    }

                    drawNode(node.left);
                    drawNode(node.right);
                };

                const drawEdge = (parent, child) => {
                    const dx = child.x - parent.x;
                    const dy = child.y - parent.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    const ratio = (distance - nodeRadius.value) / distance;
                    const endX = parent.x + dx * ratio;
                    const endY = parent.y + dy * ratio;

                    ctx.value.beginPath();
                    ctx.value.moveTo(parent.x, parent.y);
                    ctx.value.lineTo(endX, endY);
                    const gradient = ctx.value.createLinearGradient(parent.x, parent.y, endX, endY);
                    if (hoveredEdge.value && hoveredEdge.value[0] === parent && hoveredEdge.value[1] === child) {
                        gradient.addColorStop(0, '#3498db');
                        gradient.addColorStop(1, '#2980b9');
                        ctx.value.lineWidth = 4;
                    } else {
                        gradient.addColorStop(0, '#95a5a6');
                        gradient.addColorStop(1, '#7f8c8d');
                        ctx.value.lineWidth = 2;
                    }
                    ctx.value.strokeStyle = gradient;
                    ctx.value.stroke();
                };

                const animate = () => {
                    if (root.value) animateNode(root.value);
                    drawTree();
                    requestAnimationFrame(animate);
                };

                const animateNode = (node) => {
                    if (!node) return;
                    node.x += (node.targetX - node.x) * animationSpeed;
                    node.y += (node.targetY - node.y) * animationSpeed;
                    animateNode(node.left);
                    animateNode(node.right);
                };

                const generateTree = () => {
                    const values = treeInput.value.split(',').map(val => val.trim());
                    console.log('Tree Input:', values); // Debug the input
                    root.value = buildTree(values);

                    if (!root.value) {
                        console.error("Tree could not be built");
                        return;
                    }
                    
                    layoutTree(root.value);
                    console.log('Tree generated and laid out'); // Confirm tree is built
                };




                const findNodeAtPosition = (x, y, node = root.value) => {
                    if (!node) return null;
                    const distance = Math.sqrt((node.x - x) ** 2 + (node.y - y) ** 2);
                    if (distance <= nodeRadius.value) return node;
                    const leftResult = findNodeAtPosition(x, y, node.left);
                    if (leftResult) return leftResult;
                    return findNodeAtPosition(x, y, node.right);
                };

                const findEdgeAtPosition = (x, y, node = root.value) => {
                    if (!node) return null;
                    if (node.left && isPointNearLine(x, y, node.x, node.y, node.left.x, node.left.y)) {
                        return [node, node.left];
                    }
                    if (node.right && isPointNearLine(x, y, node.x, node.y, node.right.x, node.right.y)) {
                        return [node, node.right];
                    }
                    const leftResult = findEdgeAtPosition(x, y, node.left);
                    if (leftResult) return leftResult;
                    return findEdgeAtPosition(x, y, node.right);
                };

                const isPointNearLine = (x, y, x1, y1, x2, y2, tolerance = 5) => {
                    const A = x - x1;
                    const B = y - y1;
                    const C = x2 - x1;
                    const D = y2 - y1;
                    const dot = A * C + B * D;
                    const lenSq = C * C + D * D;
                    let param = -1;
                    if (lenSq !== 0) param = dot / lenSq;
                    let xx, yy;
                    if (param < 0) {
                        xx = x1;
                        yy = y1;
                    } else if (param > 1) {
                        xx = x2;
                        yy = y2;
                    } else {
                        xx = x1 + param * C;
                        yy = y1 + param * D;
                    }
                    const dx = x - xx;
                    const dy = y - yy;
                    return Math.sqrt(dx * dx + dy * dy) <= tolerance;
                };

                const onMouseDown = (event) => {
                const rect = canvas.value.getBoundingClientRect();
                const x = event.clientX - rect.left;
                const y = event.clientY - rect.top;
                selectedNode.value = findNodeAtPosition(x, y);
            };

            const onMouseUp = () => {
                if (selectedNode.value && potentialParent.value) {
                    // Attach the dragged node as a child of the potential parent
                    if (!potentialParent.value.left) {
                        potentialParent.value.left = selectedNode.value;
                    } else if (!potentialParent.value.right) {
                        potentialParent.value.right = selectedNode.value;
                    }
                    layoutTree(root.value);
                }
                selectedNode.value = null;
                potentialParent.value = null;
            };

            // Ensure canvas is properly initialized in onMounted
            onMounted(() => {
                nextTick(() => {
                    canvas.value = document.querySelector('canvas'); // Manually select the canvas
                    if (canvas.value) {
                        ctx.value = canvas.value.getContext('2d');
                        canvas.value.width = window.innerWidth;
                        canvas.value.height = window.innerHeight - 150; // Adjust for controls height

                        console.log('Canvas initialized:', canvas.value.width, canvas.value.height);

                        generateTree();
                        animate();
                    } else {
                        console.error("Canvas is not available");
                    }
                });
            });


            watch(treeInput, generateTree);

            return {
                canvas,
                treeInput,
                generateTree,
                onMouseMove,   // Add this
                onMouseDown,   // Add this
                onMouseUp,     // Add this
            };

        }
    }).mount('#app');
</script>
</body> 
</html>