{% extends "base.html" %}

{% block head %}
    <script src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script>
{% endblock %}

{% block css %}
#mynetwork {
    width: 100%;
    height: 100vh;
    border: 1px solid #ddd;
    background-color: #f8f9fa;
    border-radius: 10px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.search-container {
    position: absolute;
    bottom: 100px;
    left: 10px;
    z-index: 10;
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.search-container input,
.search-container select,
.search-container button {
    padding: 8px;
    border-radius: 8px;
    border: 1px solid #ccc;
}

.search-container button {
    background-color: #007bff;
    color: white;
    cursor: pointer;
}

.search-container button:hover {
    background-color: #0056b3;
}

#node-info {
    position: absolute;
    bottom: 10px;
    right: 10px;
    background-color: rgba(255, 255, 255, 0.95);
    padding: 12px;
    border-radius: 8px;
    border: 1px solid #ccc;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
    font-size: 14px;
    color: #333;
    width: 260px;
    max-height: 250px;
    overflow-y: auto;
}

#legend {
    position: absolute;
    bottom: 10px;
    left: 10px;
    background: rgba(255, 255, 255, 0.9);
    padding: 10px;
    border-radius: 5px;
    border: 1px solid #ccc;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    font-size: 14px;
}

.legend-box {
    display: inline-block;
    width: 12px;
    height: 12px;
    margin-right: 5px;
    border-radius: 3px;
}
{% endblock %}

{% block body %}
<div id="mynetwork"></div>

<div class="search-container">
    <label for="channel-select" style="color: #333;">Channel:</label>
    <select id="channel-select" onchange="filterByChannel()"></select>
    <input type="text" id="node-search" placeholder="Search node...">
    <button onclick="searchNode()">Search</button>
</div>

<div id="node-info">
    <b>Long Name:</b> <span id="node-long-name"></span><br>
    <b>Short Name:</b> <span id="node-short-name"></span><br>
    <b>Role:</b> <span id="node-role"></span><br>
    <b>Hardware Model:</b> <span id="node-hw-model"></span>
</div>

<div id="legend">
    <div><span class="legend-box" style="background-color: #ff5733;"></span> <span style="color: black;">Traceroute</span></div>
    <div><span class="legend-box" style="background-color: #3388ff;"></span> <span style="color: black;">Neighbor</span></div>
</div>

<script type="text/javascript">
    const chart = echarts.init(document.getElementById('mynetwork'));

    const nodes = [
    {% for node in nodes %}
        {
            name: `{{ node.node_id }}`,
            value: `{{ node.long_name | tojson }}`,
            symbol: 'circle',
            symbolSize: 15,
            itemStyle: { color: '#007bff', opacity: 1},
            label: {
                show: true,
                position: 'right',
                color: '#333',
                fontSize: 12,
                formatter: function(params) {
                    return params.data.value.replace(/^\"(.*)\"$/, '$1');
                }
            },
            long_name: `{{ node.long_name }}`,
            short_name: `{{ node.short_name }}`,
            role: `{{ node.role }}`,
            hw_model: `{{ node.hw_model }}`,
            channel: `{{ node.channel }}`
        }{% if not loop.last %},{% endif %}
    {% endfor %}
    ];

    const edges = [
    {% for edge in edges %}
        {
            source: `{{ edge.from }}`,
            target: `{{ edge.to }}`,
            originalColor: `{{ edge.originalColor }}`,
            lineStyle: {
                color: '#d3d3d3',
                width: 2,
                opacity: 1
            }
        }{% if not loop.last %},{% endif %}
    {% endfor %}
    ];

    let filteredNodes = [];
    let filteredEdges = [];
    let selectedChannel = 'LongFast';
    let lastSelectedNode = null;

    function populateChannelDropdown() {
        const channelSelect = document.getElementById('channel-select');
        const uniqueChannels = [...new Set(nodes.map(n => n.channel).filter(Boolean))].sort();

        for (const ch of uniqueChannels) {
            const option = document.createElement('option');
            option.value = ch;
            option.text = ch;
            if (ch === 'LongFast') option.selected = true;
            channelSelect.appendChild(option);
        }

        selectedChannel = channelSelect.value;
        filterByChannel();
    }

    function filterByChannel() {
        selectedChannel = document.getElementById('channel-select').value;
        filteredNodes = nodes.filter(n => n.channel === selectedChannel);
        const nodeSet = new Set(filteredNodes.map(n => n.name));
        filteredEdges = edges.filter(e => nodeSet.has(e.source) && nodeSet.has(e.target));
        lastSelectedNode = null;
        updateChart();
    }

    function updateChart() {
        const updatedNodes = filteredNodes.map(node => {
            let opacity = 1;
            let color = '#007bff';
            if (lastSelectedNode) {
                const connected = filteredEdges.some(e =>
                    (e.source === node.name && e.target === lastSelectedNode) ||
                    (e.target === node.name && e.source === lastSelectedNode)
                );
                if (node.name === lastSelectedNode) {
                    color = '#ff8c00'; // selected node orange
                    opacity = 1;
                } else if (connected) {
                    opacity = 1; // keep neighbors visible
                } else {
                    opacity = 0.4; // dim unrelated
                }
            }
            return {
                ...node,
                itemStyle: { color, opacity }
            };
        });

        const updatedEdges = filteredEdges.map(edge => {
            let opacity = .1;
            let width = 2;
            if (lastSelectedNode) {
                const connected = edge.source === lastSelectedNode || edge.target === lastSelectedNode;
                opacity = connected ? 1 : 0.05;
                width = connected ? 2 : 1;
            }
            return {
                ...edge,
                lineStyle: {
                    color: edge.originalColor || '#d3d3d3',
                    width,
                    opacity
                }
            };
        });

        chart.setOption({
            series: [{
                type: 'graph',
                layout: 'force',
                data: updatedNodes,
                links: updatedEdges,
                roam: true,
                force: { repulsion: 200, edgeLength: [80, 120] }
            }]
        });
    }

    chart.on('click', function (params) {
        if (params.dataType === 'node') {
            updateSelectedNode(params.data.name);
        } else {
            // background click -> reset
            lastSelectedNode = null;
            updateChart();
            document.getElementById('node-long-name').innerText = '';
            document.getElementById('node-short-name').innerText = '';
            document.getElementById('node-role').innerText = '';
            document.getElementById('node-hw-model').innerText = '';
        }
    });

    function updateSelectedNode(selectedNode) {
        lastSelectedNode = selectedNode;
        updateChart();

        const nodeData = filteredNodes.find(n => n.name === selectedNode);
        if (nodeData) {
            document.getElementById('node-long-name').innerText = nodeData.long_name;
            document.getElementById('node-short-name').innerText = nodeData.short_name;
            document.getElementById('node-role').innerText = nodeData.role;
            document.getElementById('node-hw-model').innerText = nodeData.hw_model;
        }
    }

    function searchNode() {
        const query = document.getElementById('node-search').value.toLowerCase().trim();
        if (!query) return;

        const found = filteredNodes.find(node =>
            node.name.toLowerCase().includes(query) ||
            node.long_name.toLowerCase().includes(query) ||
            node.short_name.toLowerCase().includes(query)
        );

        if (found) {
            updateSelectedNode(found.name);
        } else {
            alert("Node not found in current channel!");
        }
    }

    populateChannelDropdown();
</script>
{% endblock %}
