<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AS215085 - Router tools | BGP table</title>
    <link rel="icon" type="image/png" href="../static/img/cropped-Pixelhosting-logo-favicon-32x32.png">
    <script src="../static/js/bootstrap.bundle.min.js"></script>
    <link href="../static/css/bootstrap.min.css" rel="stylesheet">
    <link href="../static/css/style.css" rel="stylesheet">
</head>
<body>
    <header>
        <div class="header-content">
            <a href="/"> <img src="../static/img/as215085-logo.png" alt="AS215085 Logo" style="height: 120px; opacity: 1;!important"> </a>
            <h2><b>core1.doet.pixelhosting.nl</b></h2>
            <p><b>Proudly delivering the backbone for PixelHosting’s services</b></p>
        </div>
    </header>
    <nav class="navbar navbar-expand-lg navbar-light" style="background-color: #07AAF9;">
        <div class="container-fluid">
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNav">
                <ul class="navbar-nav justify-content-center w-100">
                    <li class="nav-item"><a class="nav-link text-white" href="/">Home</a></li>
                    <li class="nav-item"><a class="nav-link text-white" href="/bgp">BGP summary</a></li>
                    <li class="nav-item"><a class="nav-link text-white" href="/bgp-route">BGP route</a></li>
                    <li class="nav-item"><a class="nav-link text-white" href="/arp">ARP table</a></li>
                    <li class="nav-item"><a class="nav-link text-white" href="/neighbors">Neighbors table</a></li>
                    <li class="nav-item"><a class="nav-link text-white" href="/interfaces">Interfaces table</a></li>
                </ul>
            </div>
        </div>
    </nav>
    <main>
    <section id="bgp-v4">
      <h4>IPv4 Unicast Summary</h4>
      <p id="ipv4Summary">Loading summary...</p>
          <div class="input-group mb-3">
              <input type="text" id="ipv4Search" class="form-control" placeholder="Search in IPv4 table..." onkeyup="filterTable('ipv4Search', 'ipv4Table')">
              <button id="refreshButton" class="btn btn-outline-primary" type="button" onclick="refreshBGPTable()">
                  <span id="refreshIcon">⟳</span>
                  <span id="refreshSpinner" class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
                  Refresh data
              </button>
          </div>
      <table class="striped" id="ipv4Table">
        <thead>
          <tr>
            <th class="sortable" onclick="sortTable('ipv4Table', 0, this)">Neighbor <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv4Table', 1, this)">Version <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv4Table', 2, this)">AS Number <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv4Table', 3, this)">Messages Received <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv4Table', 4, this)">Messages Sent <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv4Table', 5, this)">Table Version <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv4Table', 6, this)">Inbound Queue <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv4Table', 7, this)">Outbound Queue <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv4Table', 8, this)">Up/Down <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv4Table', 9, this)">State/PfxRcd <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv4Table', 10, this)">Prefix Sent <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv4Table', 11, this)">Description <span class="sort-arrow"></span></th>
          </tr>
        </thead>
        <tbody id="ipv4TableBody">
          <tr>
            <td colspan="12" class="text-center">
              <div class="spinner-border text-primary" role="status">
                <span class="visually-hidden">Loading...</span>
              </div>
            </td>
          </tr>
        </tbody>
      </table>
      <p><a href="/bgp/json">JSON version</a></p>
    </section>

    <section id="bgp-v6">
      <h4>IPv6 Unicast Summary</h4>
      <p id="ipv6Summary">Loading summary...</p>
          <div class="input-group mb-3">
              <input type="text" id="ipv6Search" class="form-control" placeholder="Search in IPv6 table..." onkeyup="filterTable('ipv6Search', 'ipv6Table')">
              <button id="refreshButton" class="btn btn-outline-primary" type="button" onclick="refreshBGPTable()">
                  <span id="refreshIcon2">⟳</span>
                  <span id="refreshSpinner2" class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
                  Refresh data
              </button>
          </div>
      <table class="striped" id="ipv6Table">
        <thead>
          <tr>
            <th class="sortable" onclick="sortTable('ipv6Table', 0, this)">Neighbor <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv6Table', 1, this)">Version <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv6Table', 2, this)">AS Number <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv6Table', 3, this)">Messages Received <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv6Table', 4, this)">Messages Sent <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv6Table', 5, this)">Table Version <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv6Table', 6, this)">Inbound Queue <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv6Table', 7, this)">Outbound Queue <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv6Table', 8, this)">Up/Down <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv6Table', 9, this)">State/PfxRcd <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv6Table', 10, this)">Prefix Sent <span class="sort-arrow"></span></th>
            <th class="sortable" onclick="sortTable('ipv6Table', 11, this)">Description <span class="sort-arrow"></span></th>
          </tr>
        </thead>
        <tbody id="ipv6TableBody">
          <tr>
            <td colspan="12" class="text-center">
              <div class="spinner-border text-primary" role="status">
                <span class="visually-hidden">Loading...</span>
              </div>
            </td>
          </tr>
        </tbody>
      </table>
      <p><a href="/bgp/json">JSON version</a></p>
    </section>
    </main>
    <footer>
        <p>&copy; 2020 – <span id="year"></span> AS215085 (PixelHosting). All rights reserved.</p>
        <script> document.getElementById("year").textContent = new Date().getFullYear(); </script>
    </footer>
    <script src="../static/js/materialize.min.js"></script>
    <script>
        function filterTable(searchInputId, tableId) {
            const input = document.getElementById(searchInputId);
            const filter = input.value.toUpperCase();
            const table = document.getElementById(tableId);
            const tr = table.getElementsByTagName("tr");

            for (let i = 1; i < tr.length; i++) {
                tr[i].style.display = "none";
                const td = tr[i].getElementsByTagName("td");
                for (let j = 0; j < td.length; j++) {
                    if (td[j]) {
                        const txtValue = td[j].textContent || td[j].innerText;
                        if (txtValue.toUpperCase().indexOf(filter) > -1) {
                            tr[i].style.display = "";
                            break;
                        }
                    }
                }
            }
        }

        function sortTable(tableId, columnIndex, th) {
            const table = document.getElementById(tableId);
            const tbody = table.tBodies[0];
            const rows = Array.from(tbody.rows);
            const headers = Array.from(th.parentNode.children);

            headers.forEach(header => {
                if (header !== th) {
                    header.classList.remove('asc', 'desc');
                    header.setAttribute('data-sort-state', 'none');
                }
            });

            let currentState = th.getAttribute('data-sort-state') || 'none';
            let newState = currentState === 'none' ? 'asc' : currentState === 'asc' ? 'desc' : 'none';

            th.classList.remove('asc', 'desc');
            if (newState !== 'none') th.classList.add(newState);
            th.setAttribute('data-sort-state', newState);

            if (newState === 'none') {
                rows.sort((a, b) => parseInt(a.getAttribute('data-index')) - parseInt(b.getAttribute('data-index')));
            } else {
                rows.sort((a, b) => {
                    const aText = a.cells[columnIndex].textContent.trim();
                    const bText = b.cells[columnIndex].textContent.trim();

                    const aNum = parseFloat(aText.replace(/[^0-9.-]/g, ''));
                    const bNum = parseFloat(bText.replace(/[^0-9.-]/g, ''));
                    const isNumeric = !isNaN(aNum) && !isNaN(bNum);

                    return newState === 'asc'
                        ? (isNumeric ? aNum - bNum : aText.localeCompare(bText))
                        : (isNumeric ? bNum - aNum : bText.localeCompare(aText));
                });
            }

            rows.forEach(row => tbody.appendChild(row));
        }
		
        async function loadBgpTables() {
          const ipv4SummaryEl = document.getElementById("ipv4Summary");
          const ipv6SummaryEl = document.getElementById("ipv6Summary");
          const ipv4Body = document.getElementById("ipv4TableBody");
          const ipv6Body = document.getElementById("ipv6TableBody");

          try {
            const response = await fetch("/bgp/json");
            const data = await response.json();

            ipv4SummaryEl.innerHTML = `
              <p>BGP Router ID: ${data.ipv4_info.router_id}, Local AS Number: ${data.ipv4_info.local_as} VRF ID: ${data.ipv4_info.vrf_id}</p>
              <p>BGP Table Version: ${data.ipv4_info.table_version}</p>
              <p>RIB Entries: ${data.ipv4_info.rib_entries}, using ${data.ipv4_info.rib_memory}</p>
              <p>Peers: ${data.ipv4_info.peers}, using ${data.ipv4_info.peers_memory}</p>
            `;

            ipv6SummaryEl.innerHTML = `
              <p>BGP Router ID: ${data.ipv6_info.router_id}, Local AS Number: ${data.ipv6_info.local_as} VRF ID: ${data.ipv6_info.vrf_id}</p>
              <p>BGP Table Version: ${data.ipv6_info.table_version}</p>
              <p>RIB Entries: ${data.ipv6_info.rib_entries}, using ${data.ipv6_info.rib_memory}</p>
              <p>Peers: ${data.ipv6_info.peers}, using ${data.ipv6_info.peers_memory}</p>
            `;

            ipv4Body.innerHTML = "";
            if (data.ipv4_peers.length === 0) {
              ipv4Body.innerHTML = `<tr><td colspan="12" class="text-center">Geen data beschikbaar.</td></tr>`;
            } else {
              data.ipv4_peers.forEach((peer, index) => {
                const row = document.createElement("tr");
                row.setAttribute("data-index", index);
                row.innerHTML = `
                  <td>${peer.neighbor}</td>
                  <td>${peer.version}</td>
                  <td>${peer.as_number}</td>
                  <td>${peer.msg_received}</td>
                  <td>${peer.msg_sent}</td>
                  <td>${peer.table_version}</td>
                  <td>${peer.in_queue}</td>
                  <td>${peer.out_queue}</td>
                  <td>${peer.up_down}</td>
                  <td>${peer.state_pfx_rcd}</td>
                  <td>${peer.prefix_sent}</td>
                  <td>${peer.description}</td>
                `;
                ipv4Body.appendChild(row);
              });
            }

            ipv6Body.innerHTML = "";
            if (data.ipv6_peers.length === 0) {
              ipv6Body.innerHTML = `<tr><td colspan="12" class="text-center">Geen data beschikbaar.</td></tr>`;
            } else {
              data.ipv6_peers.forEach((peer, index) => {
                const row = document.createElement("tr");
                row.setAttribute("data-index", index);
                row.innerHTML = `
                  <td>${peer.neighbor}</td>
                  <td>${peer.version}</td>
                  <td>${peer.as_number}</td>
                  <td>${peer.msg_received}</td>
                  <td>${peer.msg_sent}</td>
                  <td>${peer.table_version}</td>
                  <td>${peer.in_queue}</td>
                  <td>${peer.out_queue}</td>
                  <td>${peer.up_down}</td>
                  <td>${peer.state_pfx_rcd}</td>
                  <td>${peer.prefix_sent}</td>
                  <td>${peer.description}</td>
                `;
                ipv6Body.appendChild(row);
              });
            }
          } catch (error) {
            ipv4SummaryEl.textContent = "Fout bij ophalen IPv4 data.";
            ipv6SummaryEl.textContent = "Fout bij ophalen IPv6 data.";
            ipv4Body.innerHTML = `<tr><td colspan="12" class="text-center text-danger">Fout bij ophalen van data.</td></tr>`;
            ipv6Body.innerHTML = `<tr><td colspan="12" class="text-center text-danger">Fout bij ophalen van data.</td></tr>`;
          }
        }

        window.addEventListener("DOMContentLoaded", () => {
          loadBgpTables();
        });
		
		function refreshBGPTable() {
            const searchInput = document.getElementById("ipv4Search");
            const searchInput2 = document.getElementById("ipv6Search");
            const refreshIcon = document.getElementById("refreshIcon");
            const refreshIcon2 = document.getElementById("refreshIcon2");
            const refreshSpinner = document.getElementById("refreshSpinner");
            const refreshSpinner2 = document.getElementById("refreshSpinner2");

            searchInput.value = ""; // Leegmaken van het zoekveld
            searchInput2.value = ""; // Leegmaken van het zoekveld

            refreshIcon.classList.add("d-none");
            refreshIcon2.classList.add("d-none");
            refreshSpinner.classList.remove("d-none");
            refreshSpinner2.classList.remove("d-none");

            loadBgpTables().then(() => {
                refreshIcon.classList.remove("d-none");
                refreshIcon2.classList.remove("d-none");
                refreshSpinner.classList.add("d-none");
                refreshSpinner2.classList.add("d-none");
            });
        }
    </script>
</body>
</html>