{% extends "base.html" %}

{% block title %}{{ database }}: Table diagram{% endblock %}

{% block crumbs %}
<p class="crumbs">
    <a href="/">home</a> /
    <a href="{{ urls.database(database) }}">{{ database }}</a> /
    Table diagram
</p>
{% endblock %}

{% block content %}
<div id="diagram-layout" style="
    display: flex;
    flex-direction: column;
    height: calc(100vh - 100px);
    min-height: 400px;
">
    <div id="diagram-container" style="
        overflow: auto;
        border: 1px solid #ccc;
        cursor: grab;
        flex: 1;
        min-height: 0;
    ">
        <div id="diagram-inner">
            <pre class="mermaid">{{ mermaid_text|safe }}</pre>
        </div>
    </div>
    <div style="margin-top: 8px; display: flex; gap: 8px; align-items: center; flex-shrink: 0;">
        <button id="zoom-in" title="Zoom in" style="padding: 4px 10px; font-size: 18px;">+</button>
        <button id="zoom-out" title="Zoom out" style="padding: 4px 10px; font-size: 18px;">&minus;</button>
        <button id="zoom-reset" title="Reset zoom" style="padding: 4px 10px;">Reset</button>
        <span id="zoom-level" style="color: #666; font-size: 14px;">100%</span>
    </div>
    <p id="table-links" style="margin: 4px 0 0 0; line-height: 1.8; flex-shrink: 0;">
        {% for table in tables %}
            <a href="#" data-table="{{ table }}" style="white-space: nowrap;">{{ table }}</a>{% if not loop.last %}, {% endif %}
        {% endfor %}
    </p>
</div>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });

// Wait for mermaid to render, then set up zoom/pan
setTimeout(() => {
    var container = document.getElementById('diagram-container');
    var inner = document.getElementById('diagram-inner');
    var svg = inner.querySelector('svg');
    if (!svg) return;

    // Remove mermaid's default max-width constraint
    svg.style.maxWidth = 'none';

    var scale = 1;
    var ZOOM_STEP = 0.2;
    var MIN_SCALE = 0.3;
    var MAX_SCALE = 5;

    function setScale(s) {
        scale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, s));
        inner.style.transform = 'scale(' + scale + ')';
        inner.style.transformOrigin = 'top left';
        document.getElementById('zoom-level').textContent = Math.round(scale * 100) + '%';
    }

    function repeatWhileHeld(button, fn) {
        var timer = null;
        var start = function(e) {
            e.preventDefault();
            fn();
            timer = setInterval(fn, 150);
        };
        var stop = function() { clearInterval(timer); timer = null; };
        button.addEventListener('mousedown', start);
        button.addEventListener('mouseup', stop);
        button.addEventListener('mouseleave', stop);
        button.addEventListener('touchstart', start);
        button.addEventListener('touchend', stop);
        button.addEventListener('touchcancel', stop);
    }
    repeatWhileHeld(document.getElementById('zoom-in'), function() { setScale(scale + ZOOM_STEP); });
    repeatWhileHeld(document.getElementById('zoom-out'), function() { setScale(scale - ZOOM_STEP); });
    document.getElementById('zoom-reset').addEventListener('click', function() { setScale(1); });

    // Scroll wheel zoom
    container.addEventListener('wheel', function(e) {
        if (e.ctrlKey || e.metaKey) {
            e.preventDefault();
            setScale(scale + (e.deltaY < 0 ? ZOOM_STEP : -ZOOM_STEP));
        }
    }, { passive: false });

    // Drag to pan
    var isDragging = false;
    var startX, startY, scrollLeft, scrollTop;

    container.addEventListener('mousedown', function(e) {
        isDragging = true;
        container.style.cursor = 'grabbing';
        startX = e.pageX - container.offsetLeft;
        startY = e.pageY - container.offsetTop;
        scrollLeft = container.scrollLeft;
        scrollTop = container.scrollTop;
    });

    container.addEventListener('mouseleave', function() {
        isDragging = false;
        container.style.cursor = 'grab';
    });

    container.addEventListener('mouseup', function() {
        isDragging = false;
        container.style.cursor = 'grab';
    });

    container.addEventListener('mousemove', function(e) {
        if (!isDragging) return;
        e.preventDefault();
        var x = e.pageX - container.offsetLeft;
        var y = e.pageY - container.offsetTop;
        container.scrollLeft = scrollLeft - (x - startX);
        container.scrollTop = scrollTop - (y - startY);
    });

    // Build map of table name -> SVG entity group
    var entityMap = {};
    var entityGroups = svg.querySelectorAll('g[id^="entity-"]');
    for (var i = 0; i < entityGroups.length; i++) {
        var g = entityGroups[i];
        // ID format: entity-{name}-{index}
        var match = g.id.match(/^entity-(.+)-\d+$/);
        if (match) {
            entityMap[match[1]] = g;
        }
    }

    // Zoom to entity function
    function zoomToEntity(tableName) {
        // Mermaid uses the sanitized name (special chars -> _) as the entity ID
        var sanitized = tableName.replace(/[^a-zA-Z0-9_ -]/g, '_');
        var entity = entityMap[sanitized];
        if (!entity) return;

        // Get the entity's position in SVG coordinates
        var svgRect = svg.getBoundingClientRect();
        var entityRect = entity.getBoundingClientRect();

        // Calculate entity position relative to the unscaled SVG
        var entityX = (entityRect.left - svgRect.left) / scale;
        var entityY = (entityRect.top - svgRect.top) / scale;
        var entityW = entityRect.width / scale;
        var entityH = entityRect.height / scale;

        // Calculate scale to fit entity with some padding
        var padding = 40;
        var scaleX = container.clientWidth / (entityW + padding * 2);
        var scaleY = container.clientHeight / (entityH + padding * 2);
        var newScale = Math.min(scaleX, scaleY, MAX_SCALE);
        newScale = Math.max(newScale, MIN_SCALE);

        setScale(newScale);

        // Scroll to center the entity in the container
        container.scrollLeft = (entityX - padding) * newScale - (container.clientWidth - (entityW + padding * 2) * newScale) / 2;
        container.scrollTop = (entityY - padding) * newScale - (container.clientHeight - (entityH + padding * 2) * newScale) / 2;
    }

    // Wire up table links
    var links = document.querySelectorAll('#table-links a[data-table]');
    for (var i = 0; i < links.length; i++) {
        links[i].addEventListener('click', function(e) {
            e.preventDefault();
            zoomToEntity(this.getAttribute('data-table'));
        });
    }

    // Start zoomed to fit width
    var containerWidth = container.clientWidth;
    var svgWidth = svg.getBoundingClientRect().width;
    if (svgWidth > containerWidth) {
        setScale(containerWidth / svgWidth);
    }
}, 500);
</script>
{% endblock %}
