{% 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;1
    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;
    display: flex;
    color: #333;
}
.legend-category {
    margin-right: 10px;
    code {
        color: inherit;
    }
}
.legend-box {
    display: inline-block;
    width: 12px;
    height: 12px;
    margin-right: 5px;
    border-radius: 3px;
    &.circle {
        border-radius: 6px;
    }
}
{% 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 class="legend-category">
        <div><span class="legend-box" style="background-color: #ff5733"></span> Traceroute</div>
        <div><span class="legend-box" style="background-color: #049acd"></span> Neighbor</div>
    </div>
    <div class="legend-category">
        <div><span class="legend-box circle" style="background-color: #ff5733"></span> <code>ROUTER</code></div>
        <div><span class="legend-box circle" style="background-color: #b65224"></span> <code>ROUTER_LATE</code></div>
    </div>
    <div class="legend-category">
        <div><span class="legend-box circle" style="background-color: #007bff"></span> <code>CLIENT</code></div>
        <div><span class="legend-box circle" style="background-color: #00c3ff"></span> <code>CLIENT_MUTE</code></div>
    </div>
    <div class="legend-category">
        <div><span class="legend-box circle" style="background-color: #049acd"></span> <code>CLIENT_BASE</code></div>
        <div><span class="legend-box circle" style="background-color: #ffbf00"></span> Other</div>
    </div>
    <div class="legend-category">
        <div><span class="legend-box circle" style="background-color: #6c757d"></span> Unknown</div>
    </div>
</div>

<script>
const chart = echarts.init(document.getElementById('mynetwork'));

const colors = {
    edge: {
        traceroute: '#ff5733',
        neighbor: '#049acd',
    },
    role: {
        ROUTER: '#ff5733',
        ROUTER_LATE: '#b65224',
        CLIENT: '#007bff',
        CLIENT_MUTE: '#00c3ff',
        CLIENT_BASE: '#049acd',
        other: '#ffbf00',
        unknown: '#6c757d',
    },
    selection: '#ff8c00',
};

function getRoleColor(role) {
    if (!role) return colors.role.unknown;
    return colors.role[role] || colors.role.other;
}


function getSymbolSize (role) {
    switch (role) {
        case 'ROUTER': return 30;
        case 'ROUTER_LATE': return 30;
        case 'CLIENT_BASE': return 18;
        case 'CLIENT': return 15;
        case 'CLIENT_MUTE': return 7;
        default: return 15; // Unknown or other roles
    }
}

function getLabel (role, short_name, long_name) {
    if (role === 'ROUTER') return long_name;
    if (role === 'ROUTER_LATE') return long_name;
    if (role === 'CLIENT_BASE') return short_name;
    if (role === 'CLIENT') return short_name;
    if (role === 'CLIENT_MUTE') return short_name;
    return short_name || '';
}

// --- Nodes ---
const nodes = [
{% for node in nodes %}
{
    name: "{{ node.node_id }}",                // node_id as string
    value: getLabel({{node.role | tojson}}, {{node.short_name | tojson }}, {{node.long_name | tojson}}),     // display label
    symbol: 'circle',
    symbolSize: getSymbolSize({{node.role | tojson}}),
    itemStyle: { color: getRoleColor({{node.role | tojson}}), opacity:1 },
    label: { show:true, position:'right', color:'#333', fontSize:12, formatter: (p)=>p.data.value },
    long_name: {{ node.long_name | tojson }},
    short_name: {{ node.short_name | tojson }},
    role: {{ node.role | tojson }},
    hw_model: {{ node.hw_model | tojson }},
    channel: {{ node.channel | tojson }}
},
{% endfor %}
];

// --- Edges ---
const edges = [
{% for edge in edges %}
{
    source: "{{ edge.from }}",   // edge source as string
    target: "{{ edge.to }}",     // edge target as string
    originalColor: colors.edge[{{edge.type | tojson}}],
    lineStyle: {
        color: colors.edge[{{edge.type | tojson}}],
        width: {{edge.weight | tojson}},
    },
},
{% endfor %}
];

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

function populateChannelDropdown() {
    const sel = document.getElementById('channel-select');
    const unique = [...new Set(nodes.map(n=>n.channel).filter(Boolean))].sort();
    unique.forEach(ch=>{
        const opt = document.createElement('option');
        opt.value=ch; opt.text=ch;
        if(ch==='LongFast') opt.selected=true;
        sel.appendChild(opt);
    });
    selectedChannel = sel.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, color=getRoleColor(node.role), borderColor='transparent', borderWidth=6;
        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) {
                opacity=1;
                borderColor=colors.selection;
            }
            else if(connected) opacity=1;
            else opacity=0.4;
        }
        return {...node, itemStyle:{...node.itemStyle, color,opacity, borderColor, borderWidth}};
    });

    const updatedEdges = filteredEdges.map(edge=>{
        let opacity=0.1, width=edge.lineStyle.width;
        if(lastSelectedNode){
            const connected = edge.source===lastSelectedNode || edge.target===lastSelectedNode;
            opacity=connected?1:0.05; width=edge.lineStyle.width;
        }
        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{
        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(selNode){
    lastSelectedNode=selNode; updateChart();
    const n = filteredNodes.find(x=>x.name===selNode);
    if(n){
        document.getElementById('node-long-name').innerText=n.long_name;
        document.getElementById('node-short-name').innerText=n.short_name;
        document.getElementById('node-role').innerText=n.role;
        document.getElementById('node-hw-model').innerText=n.hw_model;
    }
}

function searchNode(){
    const q = document.getElementById('node-search').value.toLowerCase().trim();
    if(!q) return;
    const found = filteredNodes.find(n=>n.name.toLowerCase().includes(q) || n.long_name.toLowerCase().includes(q) || n.short_name.toLowerCase().includes(q));
    if(found) updateSelectedNode(found.name);
    else alert("Node not found in current channel!");
}

populateChannelDropdown();
window.addEventListener('resize', ()=>chart.resize());
</script>
{% endblock %}
