{% if node_names %}
    {{ node_names|json_script:"node-names" }}
{% endif %}
{% if send_uuid %}
    {{ send_uuid|json_script:"send-uuid" }}
{% endif %}
{% if nodes_xyz %}
    {{ nodes_xyz|json_script:"nodes-xyz" }}
{% endif %}
<script type="text/javascript">
{% if node_names %}
    const node_names = JSON.parse(document.getElementById('node-names').textContent);
{% endif %}
{% if nodes_xyz %}
    const nodes_xyz = JSON.parse(document.getElementById('nodes-xyz').textContent);
    const nodes_distances = {};
{% endif %}

var ws;

{% if update %}
    const update_id = {{ update.pk }};
    for (const apply_link of document.querySelectorAll('.auto-apply a')) {
        apply_link.addEventListener("click", function(e) {
            e.preventDefault();
            ws.send(JSON.stringify({
                ota_auto: {
                    apply: (e.target.innerHTML == 'no'),
                    reboot: (e.target.parentElement.parentElement.querySelector('.auto-reboot a').innerText == 'yes'),
                },
                recipient: parseInt(e.target.parentElement.parentElement.parentElement.dataset.recipient),
            }));
        });
    }
    for (const apply_link of document.querySelectorAll('.auto-reboot a')) {
        apply_link.addEventListener("click", function(e) {
            e.preventDefault();
            ws.send(JSON.stringify({
                ota_auto: {
                    apply: (e.target.parentElement.parentElement.querySelector('.auto-apply a').innerText == 'yes'),
                    reboot: (e.target.innerHTML == 'no'),
                },
                recipient: parseInt(e.target.parentElement.parentElement.parentElement.dataset.recipient),
            }));
        });
    }
    for (const apply_link of document.querySelectorAll('[id^=ota-recipient-] button')) {
        apply_link.addEventListener("click", function(e) {
            e.preventDefault();
            ws.send(JSON.stringify({
                ota: e.target.name,
                recipient: parseInt(e.target.parentElement.parentElement.dataset.recipient),
            }));
        });
    }
{% endif %}

function connect() {
    console.log('reconnecting websocket...');
    ws = new WebSocket((window.location.protocol=="https:"?"wss:":"ws:")+window.location.host+"/mesh/ui/ws", []);
    ws.onopen = (event) => {
        console.log('websocket connected.');
        {% if send_uuid %}
            ws.send(JSON.stringify({"send_msg": JSON.parse(document.getElementById('send-uuid').textContent)}));
        {% elif ranging_form %}
            ws.send(JSON.stringify({"subscribe": "ranging"}));
        {% elif update %}
            ws.send(JSON.stringify({"subscribe": "ota", "update_id": update_id}));
        {% else %}
            ws.send(JSON.stringify({"subscribe": "log"}));
        {% endif %}
    };
    ws.onclose = (event) => {
        window.setTimeout(connect, 500);
    }
    ws.onmessage = (event) => {
        var data = JSON.parse(event.data), line, text, cell, link_tag;
        switch(data.type) {
            case 'mesh.log_entry':
                line = document.createElement("tr");

                cell = document.createElement("td");
                cell.innerText = data.timestamp;
                line.appendChild(cell);

                cell = document.createElement("td");
                cell.innerText = data.channel;
                if (data.uplink) {
                    cell.append(document.createElement("br"));
                    link_tag = document.createElement("a");
                    link_tag.href = "/mesh/" + data.uplink;
                    link_tag.innerText = data.uplink;
                    if (node_names[data.uplink]) {
                        link_tag.innerText += " ("+node_names[data.uplink]+")";
                    }
                    cell.append(link_tag)
                }
                line.appendChild(cell);

                cell = document.createElement("td");
                link_tag = document.createElement("a");
                link_tag.href = "/mesh/" + data.node;
                link_tag.innerText = data.node;
                if (node_names[data.node]) {
                    link_tag.innerText += " ("+node_names[data.node]+")";
                }
                cell.append(link_tag);
                line.appendChild(cell);

                cell = document.createElement("td");
                cell.innerText = data.text;
                line.appendChild(cell);

                document.querySelector("tbody").prepend(line);
                break
            case 'mesh.msg_sent':
                {% if send_uuid %}
                    line = document.createElement("span");

                    text = document.createElement("span")
                    text.innerText = "sent via uplink "
                    line.appendChild(text)

                    text = document.createElement("small")
                    text.innerText = "["+data.channel+"] "
                    line.appendChild(text)

                    link_tag = document.createElement("a");
                    link_tag.href = "/mesh/" + data.uplink;
                    link_tag.innerText = data.uplink;
                    if (node_names[data.uplink]) {
                        link_tag.innerText += "("+node_names[data.uplink]+")";
                    }
                    line.appendChild(link_tag);

                    line.appendChild(document.createElement("br"));

                    document.getElementById("sending-status-"+data.recipient).appendChild(line);
                {% endif %}
                break;

            case 'mesh.ota_recipient_status':
                {% if update %}
                    var row = document.querySelector(`[id="ota-recipient-${data.update}-${data.node}"]`);
                    if (!row) break;
                    row.querySelector('.status').innerText = data.status;
                    if (data.status !== 'running') {
                        row.querySelectorAll('.auto-apply').forEach(x => x.remove());
                        row.querySelectorAll('.auto-reboot').forEach(x => x.remove());
                        row.querySelectorAll('button').forEach(x => x.remove());
                        row.querySelectorAll('.progress').forEach(x => x.remove());
                    }
                    if (data.status === 'canceled') {
                        row.querySelectorAll('.device_status').forEach(x => x.remove());
                    }
                {% endif %}
                break;

            case 'mesh.msg_received':
                {% if ranging_form %}
                    var cell, key, src_node, peer_node;
                    src_node = data.msg.src;
                    for (cell of document.querySelectorAll(`[data-range-from="${src_node}"]:not([data-range-to="${src_node}"])`)) {
                        cell.innerText = "-";
                    }
                    cell = document.querySelector(`[data-range-location="${src_node}"]`);
                    if (!cell) break;
                    if (data.position) {
                        cell.innerHTML = `Location (${data.position[0]}, ${data.position[1]}, ${data.position[2]})`;
                        if (src_node in nodes_xyz) {
                            cell.innerHTML += `<br><em>Actual: (${nodes_xyz[src_node][0]}, ${nodes_xyz[src_node][1]}, ${nodes_xyz[src_node][2]})</em>`;
                            cell.innerHTML += `<br><em>Diff: (${data.position[0]-nodes_xyz[src_node][0]}, ${data.position[1]-nodes_xyz[src_node][1]}, ${data.position[2]-nodes_xyz[src_node][2]})</em>`;

                            cell.innerHTML += '<br><em>XY: '+String(Math.round(Math.sqrt(
                                Math.pow(nodes_xyz[src_node][0]-data.position[0], 2) +
                                Math.pow(nodes_xyz[src_node][1]-data.position[1], 2)
                            )))+' // XYZ: '+String(Math.round(Math.sqrt(
                                Math.pow(nodes_xyz[src_node][0]-data.position[0], 2) +
                                Math.pow(nodes_xyz[src_node][1]-data.position[1], 2) +
                                Math.pow(nodes_xyz[src_node][2]-data.position[2], 2)
                            )));

                        }
                    } else {
                        cell.innerHTML = '';
                    }
                    for (var i=0;i<data.msg.ranges.length;i++) {
                        let range = data.msg.ranges[i];
                        peer_node = range.peer;
                        cell = document.querySelector(
                            `[data-range-from="${src_node}"][data-range-to="${peer_node}"]`
                        );
                        if (!cell) continue;
                        key = `${src_node}-${peer_node}`
                        if (!(key in nodes_distances)) {
                            if (!(src_node in nodes_xyz && peer_node in nodes_xyz)) {
                                nodes_distances[key] = null;
                            } else {
                                nodes_distances[key] = Math.round(Math.sqrt(
                                    Math.pow(nodes_xyz[src_node][0]-nodes_xyz[peer_node][0], 2) +
                                    Math.pow(nodes_xyz[src_node][1]-nodes_xyz[peer_node][1], 2) +
                                    Math.pow(nodes_xyz[src_node][2]-nodes_xyz[peer_node][2], 2)
                                ));
                            }
                        }
                        cell.innerText = (
                            ((range.distance == 0xff) ? "invalid" : `${range.distance}cm`) +
                            ` (${range.rssi}dBm)`
                        );
                        if (nodes_distances[key] != null) {
                            cell.innerHTML += `<br> <em>(actual: ${nodes_distances[key]}cm</em>)`
                            cell.innerHTML += `<br> <em>(diff: ${range.distance-nodes_distances[key]}cm</em>)`
                        }
                    }
                {% endif %}
                {% if update %}
                    var row = document.querySelector(`[id="ota-recipient-${data.msg.update_id}-${data.msg.src}"]`);
                    if (!row) break;
                    var total = parseInt(row.querySelector('.total_bytes').innerText);
                    row.querySelector('.received_bytes').innerText = data.msg.received_bytes;
                    row.querySelector('progress').value = data.msg.received_bytes;
                    row.querySelectorAll('.device_status').forEach(x => x.innerText = ' / '+data.msg.status.toLowerCase().replace("_", " "));
                    row.querySelectorAll('.auto-apply a').forEach(x => x.innerText = data.msg.auto_apply ? 'yes' : 'no');
                    row.querySelectorAll('.auto-reboot a').forEach(x => x.innerText = data.msg.auto_reboot ? 'yes' : 'no');
                    row.querySelectorAll('button[name=apply]').forEach(
                        x => x.style.display = (data.msg.received_bytes >= total && data.msg.status === "STARTED") ? 'inline-block' : 'none'
                    );
                    row.querySelectorAll('button[name=reboot]').forEach(
                        x => x.style.display = ((data.msg.received_bytes >= total && data.msg.status === "STARTED") || data.msg.status === "APPLIED") ? 'inline-block' : 'none'
                    );
                    row.querySelectorAll('.apply_and').forEach(
                        x => x.style.display = (data.msg.status === 'APPLIED') ? 'none' : 'inline'
                    );
                {% endif %}
                {% if send_uuid and msg_type == "MESH_ROUTE_REQUEST" %}
                    if (data.msg.route) {
                        line = document.createElement('tr');

                        cell = document.createElement("td");
                        link_tag = document.createElement("a");
                        link_tag.href = "/mesh/" + data.msg.src;
                        link_tag.innerText = data.msg.src;
                        if (node_names[data.msg.src]) {
                            link_tag.innerText += " ("+node_names[data.msg.src]+")";
                        }
                        cell.appendChild(link_tag);
                        line.appendChild(cell);

                        if (data.msg.route === "00:00:00:00:00:00") {
                            document.getElementById("no-routes").appendChild(line);
                        } else {
                            cell = document.createElement("td");
                            link_tag = document.createElement("a");
                            link_tag.href = "/mesh/" + data.msg.route;
                            link_tag.innerText = data.msg.route;
                            if (node_names[data.msg.route]) {
                                link_tag.innerText += " ("+node_names[data.msg.route]+")";
                            }
                            cell.append(link_tag);
                            line.appendChild(cell);

                            document.getElementById("route-responses").appendChild(line);
                        }
                    } else {
                        for (var i=0;i<data.msg.trace.length;i++) {
                            line = document.createElement('tr');

                            cell = document.createElement("td");
                            link_tag = document.createElement("a");
                            link_tag.href = "/mesh/" + data.msg.trace[i];
                            link_tag.innerText = data.msg.trace[i];
                            if (node_names[data.msg.trace[i]]) {
                                link_tag.innerText += " ("+node_names[data.msg.trace[i]]+")";
                            }
                            cell.appendChild(link_tag);
                            line.appendChild(cell);
                            document.getElementById("route-trace").appendChild(line);
                        }
                    }
                {% endif %}
                break;
        }

        console.log(data);
    }
}

connect();

</script>
