<!DOCTYPE html>
<html>
<head>
    <title>Radiosonde Auto-RX Status</title>

    <!-- Configure to work on mobile -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!-- Import style sheets (font and icons are remote, should fix) -->
    <link href="{{ url_for('static', filename='css/main.css') }}" rel="stylesheet">
    <link href="{{ url_for('static', filename='css/roboto.css') }}" rel="stylesheet">
    <link href="{{ url_for('static', filename='css/c3.min.css') }}" rel="stylesheet">
    <link href="{{ url_for('static', filename='css/leaflet.css') }}" rel="stylesheet">
    <link href="{{ url_for('static', filename='css/leaflet.fullscreen.css') }}" rel="stylesheet">
    <link href="{{ url_for('static', filename='css/autorx.css') }}" rel="stylesheet" >
    <link id='tabulatorsheet' href="{{ url_for('static', filename='css/tabulator_midnight.min.css') }}" rel='stylesheet'>

    <!-- Import local libraries -->
    <script src="{{ url_for('static', filename='js/jquery-3.6.0.min.js') }}"></script>
    <script src="{{ url_for('static', filename='js/jquery-ui.min.js') }}"></script>
    <script src="{{ url_for('static', filename='js/leaflet.js') }}"></script>
    <script src="{{ url_for('static', filename='js/leaflet-providers.js') }}"></script>
    <script src="{{ url_for('static', filename='js/Leaflet.fullscreen.min.js') }}"></script>
    <script src="{{ url_for('static', filename='js/leaflet.edgebuffer.js') }}"></script>
    <script src="{{ url_for('static', filename='js/socket.io.min.js') }}"></script>
    <script src="{{ url_for('static', filename='js/scan_chart.js') }}"></script>
    <script src="{{ url_for('static', filename='js/c3.min.js') }}"></script>
    <script src="{{ url_for('static', filename='js/d3.min.js') }}"></script>
    <script src="{{ url_for('static', filename='js/utils.js') }}"></script>
    <script src="{{ url_for('static', filename='js/autorxapi.js') }}"></script>
    <script src="{{ url_for('static', filename='js/tabulator.min.js') }}"></script>

    <script>
        var autorx_config = {
            lat: 0.0,
            lon: 0.0
        };

        var sonde_positions = {};

        var sonde_currently_following = "none";

        // Function to change CSS options when changing dark mode.
        function changeTheme(dark) {
            if (dark == false) {
                document.body.style.background = 'white';
                if (document.getElementById("log-tray").style.color == "rgb(255, 0, 0)") {
                    $('#main span').css('color', 'black')
                    $('#log-tray').css('color', 'red');
                } else {
                    $('#main span').css('color', 'black')
                }
                $('#main p').css('color', 'black')
                $('.modal-content p').css('color', 'black')
                $('.modal-content h2').css('color', 'black')
                $('.modal-content span').css('color', 'black')
                $('.modal-content').css('background-color', 'white')
                $('.close').css('color', 'black')
                $('#myBtn1').css('color', 'black')
                $('#myBtn2').css('color', 'black')
                $('#scanid').css('color', 'black')
                $('.c3-axis-y').css('fill', 'black')
                $('.c3-axis-x').css('fill', 'black')
                $('.c3-legend-item text').css('fill', 'black')
                $('.domain').css('stroke', 'black')
                $('.tick line').css('stroke', 'black')
                $('#mapid span').css('color', 'black')
                $('.sidenav').css('background-color', '#111')
                $('.settings').css('background-color', '#111')
                $('#tabulatorsheet').attr('href', '{{ url_for("static", filename="css/tabulator_simple.min.css") }}');
            } else {
                document.body.style.background = '#121212';
                if (document.getElementById("log-tray").style.color == "rgb(255, 0, 0)") {
                    $('#main span').css('color', 'white')
                    $('#log-tray').css('color', 'red');
                } else {
                    $('#main span').css('color', 'white')
                }
                $('#main p').css('color', 'white')
                $('.modal-content p').css('color', 'white')
                $('.modal-content h2').css('color', 'white')
                $('.modal-content span').css('color', 'white')
                $('.modal-content').css('background-color', 'black')
                $('.close').css('color', 'white')
                $('#myBtn1').css('color', 'white')
                $('#myBtn2').css('color', 'white')
                $('#scanid').css('color', 'white')
                $('.c3-axis-y').css('fill', 'white')
                $('.c3-axis-x').css('fill', 'white')
                $('.c3-legend-item text').css('fill', 'white')
                $('.domain').css('stroke', 'white')
                $('.tick line').css('stroke', 'white')
                $('#mapid span').css('color', 'black')
                $('.sidenav').css('background-color', '#414141')
                $('.settings').css('background-color', '#414141')
                $('#tabulatorsheet').attr('href', '{{ url_for("static", filename="css/tabulator_midnight.min.css") }}');
            }
        }

        $( document ).ready(function() {

	    namespace = '/update_status';
	    var socket_path = "{{ url_for("static", filename="") }}".replace('static/', 'socket.io')
	    var socket = io.connect(location.origin+namespace, {'path': socket_path});
 
            $.ajax({
                  // Get station.cfg file.
                  url: "get_config",
                  dataType: 'json',
                  async: false,
                  success: function(data) {
                    autorx_config = data;
                    // Update station callsign area
                    _station_call = autorx_config['habitat_uploader_callsign'];
                    if (autorx_config['aprs_user'] !== "N0CALL"){
                        _station_call += " / " + autorx_config['aprs_user'];
                    }
                    $('#station_callsign').text(_station_call);

                    // Update webpage title
//                    document.title = _station_call + " Auto-RX Status";
                      document.title = autorx_config['habitat_uploader_callsign'] + " - Radiosonde Auto-RX Status";
                    if(autorx_config["web_control"] == false){
                        $("#password-header").html("<h2>Web Control Disabled</h2>");
                        disable_web_controls();
                    }
                  }
            });

            $.ajax({
                  // Get local version number.
                  url: "get_version",
                  dataType: 'json',
                  async: true,
                  success: function(data) {
                    // Update the current version field.
                    if (getCookie('version') == 'false') {}
                    else if (getCookie('version') == 'true') {
                        $('#currentversion').text(data.current);
                    } else if ((window.innerWidth/window.innerHeight) > 1) {
                        $('#currentversion').text(data.current);
                    }

                    // Update the latest version area.
                    if(data.latest == 'Latest'){
                        //pass
                    } else if (data.latest == "Unknown"){
                        //pass
                    } else {
                        if (data.latest.includes("-beta")) {
                            $("#footertext").html("Update Available: <a href='https://github.com/projecthorus/radiosonde_auto_rx/commits/testing' target='_blank'>" + data.latest + "</a>");
                        } else {
                            $("#footertext").html("Update Available: <a href='https://github.com/projecthorus/radiosonde_auto_rx/releases' target='_blank'>" + data.latest + "</a>");
                        }
                    }
                  }
            });

            socket.on('log_event', function(msg) {
                // New log entry received.
                var log_time = new Date(msg.timestamp);
                // Check if time is UTC mode.
                if (getCookie('UTC') == 'false') {
                    // Check if entry is important.
                    var log_time_converted = log_time.toLocaleString(window.navigator.language,{hourCycle:'h23', year:"numeric", month:"2-digit", day:'2-digit', hour:'2-digit',minute:'2-digit', second:'2-digit'});
                    if (msg.level == "INFO" || msg.level == "DEBUG") {
                        var log_entry = "<tr><td>" + log_time_converted + " – " + msg.level + "<br><em style='font-size: 15px;'>" + msg.msg + "</em></td></tr>";
                    } else {
                        // If entry is important colour text red.
                        var log_entry = "<tr><td>" + log_time_converted + " – " + msg.level + "<br><em style='font-size: 15px; color:red;'>" + msg.msg + "</em></td></tr>"
                        if (msg.level == "ERROR" || msg.level == "CRITICAL") {
                            if (document.getElementById("mySidenav").offsetWidth == 0) {
                                $('#log-tray').css('color', 'red');
                            }
                        }
                    }
                } else {
                    if (msg.level == "INFO" || msg.level == "DEBUG") {
                        var log_entry = "<tr><td>"  + new Date(msg.timestamp).toISOString().replace("T", " ").replace("Z", "").slice(0, -4) + " UTC – " + msg.level + "<br><em style='font-size: 15px;'>" + msg.msg + "</em></td></tr>";
                    } else {
                        // If entry is important colour text red.
                        var log_entry = "<tr><td>"  + new Date(msg.timestamp).toISOString().replace("T", " ").replace("Z", "").slice(0, -4) + " UTC – " + msg.level + "<br><em style='font-size: 15px; color:red;'>" + msg.msg + "</em></td></tr>";
                        if (msg.level == "ERROR" || msg.level == "CRITICAL") {
                            if (document.getElementById("mySidenav").offsetWidth == 0) {
                                $('#log-tray').css('color', 'red');
                            }
                        }
                    }
                }
                // Append entry to log table.
                $('#log_data > tbody').prepend(log_entry);
            });

            setup_scan_chart();

            socket.on('scan_event', function(msg) {
                // There is Scan data ready for us!
                // Grab the latest set of data.
                $.getJSON("get_scan_data", function(data){
                    // Load the data into our data stores.
                    scan_chart_spectra.columns[0] = ['x_spectra'].concat(data.freq);
                    scan_chart_spectra.columns[1] = ['Spectra'].concat(data.power);
                    scan_chart_peaks.columns[0] = ['x_peaks'].concat(data.peak_freq);
                    scan_chart_peaks.columns[1] = ['Peaks'].concat(data.peak_lvl);
                    scan_chart_threshold.columns[0] = ['x_thresh'].concat([data.freq[0],data.freq[data.freq.length-1]]);
                    scan_chart_threshold.columns[1] = ['Threshold'].concat([data.threshold+autorx_config.snr_threshold,data.threshold+autorx_config.snr_threshold]);
                    scan_chart_latest_timestamp = data.timestamp;

                    // Do not update the scan plot if the tab is hidden, or we have the scan plot hidden.
                    if( (document.visibilityState == "hidden") || (document.getElementById("showscanbutton").checked == false) ){
                        return;
                    } else {
                        redraw_scan_chart(data);
                    }
                
                }
                );
            });

            document.addEventListener("visibilitychange", () => {
                if (document.visibilityState === "visible" && document.getElementById("showscanbutton").checked) {
                    redraw_scan_chart();
                }
            });

            socket.on('task_event', function(msg){
                update_task_list();
            });

            // Update task list now.
            update_task_list();

            // List of available map layers.
            var Mapnik = L.tileLayer.provider("OpenStreetMap.Mapnik", {edgeBufferTiles: 2});
            var DarkMatter = L.tileLayer.provider("CartoDB.DarkMatter", {edgeBufferTiles: 2});
            var Terrain = L.tileLayer.provider("Stamen.Terrain", {edgeBufferTiles: 2});
            var WorldImagery = L.tileLayer.provider("Esri.WorldImagery", {edgeBufferTiles: 2});
            var Voyager = L.tileLayer.provider("CartoDB.Voyager", {edgeBufferTiles: 2});
            var OpenTopoMap = L.tileLayer.provider("OpenTopoMap", {edgeBufferTiles: 2});

            // Add maps to baseMaps.
            var baseMaps = {
                "Mapnik": Mapnik,
                "DarkMatter": DarkMatter,
                "WorldImagery": WorldImagery,
                "Terrain": Terrain,
                "Voyager": Voyager,
                "OpenTopoMap": OpenTopoMap
            };

            // Check if user has preffered map theme.
            var x = getCookie('theme');
            if (x) {
                mapTheme = x;
            } else {
                if (getCookie('dark') == "false") {
                    mapTheme = "Mapnik"
                } else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
                    mapTheme = "DarkMatter"
                } else {
                    mapTheme = "Mapnik"
                }
            }

            // Home Icon.
            homeIcon = L.icon({
            iconUrl: "{{ url_for('static', filename='img/antenna-green.png') }}",
            iconSize: [26, 34],
            iconAnchor: [13, 34]
            });

            // Home Icon for dark mode.
            homeIconDark = L.icon({
            iconUrl: "{{ url_for('static', filename='img/antenna-green-dark.png') }}",
            iconSize: [26, 34],
            iconAnchor: [13, 34]
            });

            // Create map object.
            mymap = L.map('mapid').setView([autorx_config.station_lat, autorx_config.station_lon], 8);
            mymap.addControl(new L.Control.Fullscreen());
            if (mapTheme != 'DarkMatter' && mapTheme != 'WorldImagery') {
                home_marker = L.marker([autorx_config.station_lat, autorx_config.station_lon, autorx_config.alt],
                        {title: 'Receiver Location', icon: homeIcon}
                        ).addTo(mymap);
            } else {
                home_marker = L.marker([autorx_config.station_lat, autorx_config.station_lon, autorx_config.alt],
                        {title: 'Receiver Location', icon: homeIconDark}
                        ).addTo(mymap);
            }


            L.control.layers(baseMaps).addTo(mymap);

            baseMaps[mapTheme].addTo(mymap);

            // Update preffered them cookie on layer change.
            mymap.on('baselayerchange', function(e) {
                setCookie("theme", e['name'], 365);
                if(e['name'] == "DarkMatter" || e['name'] == "WorldImagery"){
                    home_marker.setIcon(homeIconDark);
                 }else{
                    home_marker.setIcon(homeIcon);
                 }
            });

            // Check if user has preffered map visiblity.
            if (getCookie('map') == 'false') {
                document.getElementById("showmapbutton").checked = false;
                document.getElementById("mapid").style.display = "none";
            } else {
                document.getElementById("showmapbutton").checked = true;
            }

            // Check if user has preffered table visiblity.
            if (getCookie('table') == 'false') {
                document.getElementById("showtablebutton").checked = false;
                document.getElementById("tableid").style.display = "none";
            } else {
                document.getElementById("showtablebutton").checked = true;
            }

            // Check if user has preffered follow latest sonde selection.
            if (getCookie('follow') == 'false') {
                document.getElementById("sondeAutoFollow").checked = false;
            } else {
                document.getElementById("sondeAutoFollow").checked = true;
            }

            // Check if user has UTC time selection.
            if (getCookie('UTC') == 'false') {
                document.getElementById("showUTCbutton").checked = false;
            } else {
                document.getElementById("showUTCbutton").checked = true;
            }

            // Check if user has UTC time selection.
            if (getCookie('imperial') == 'true') {
                document.getElementById("showimperialbutton").checked = true;
            } else {
                document.getElementById("showimperialbutton").checked = false;
            }

            // Check if user has version shown selection.
            if (getCookie('version') == 'false') {
                document.getElementById("showversionbutton").checked = false;
            } else if (getCookie('version') == 'true') {
                document.getElementById("showversionbutton").checked = true;
            } else if ((window.innerWidth/window.innerHeight) > 1) {
                document.getElementById("showversionbutton").checked = true;
            } else {
                document.getElementById("showversionbutton").checked = false;
            }

            // Check if user has preffered scan chart visiblity.
            if (getCookie('scan') == 'true') {
                document.getElementById("showscanbutton").checked = true;
                document.getElementById("scanid").style.display = "block";
            } else {
                document.getElementById("showscanbutton").checked = false;
                document.getElementById("scanid").style.display = "none";
            }

            // Check if user has dark mode set.
            if (getCookie('dark') == 'true') {
                document.getElementById("showdarkbutton").checked = true;
                changeTheme(true);
            } else if (getCookie('dark') == 'false') {
                document.getElementById("showdarkbutton").checked = false;
                changeTheme(false);
            } else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
                document.getElementById("showdarkbutton").checked = true;
                changeTheme(true);
            } else {
                document.getElementById("showdarkbutton").checked = false;
                changeTheme(false);
            }


            // Check if dark mode button has been ticked.
            $('#showdarkbutton').change(function() {
                if ($(this).is(":checked")) {
                    setCookie("dark", 'true', 365);
                    changeTheme(true);
                } else {
                    setCookie("dark", 'false', 365);
                    changeTheme(false);
                }
            });

            // Check if imperial units button has been ticked.
            $('#showimperialbutton').change(function() {
                if ($(this).is(":checked")) {
                    setCookie("imperial", 'true', 365);
                    location.reload();
                } else {
                    setCookie("imperial", 'false', 365);
                    location.reload();
                }
            });

            // Check if show version button has been ticked.
            $('#showversionbutton').change(function() {
                if ($(this).is(":checked")) {
                    setCookie("version", 'true', 365);
                    location.reload();
                } else {
                    setCookie("version", 'false', 365);
                    location.reload();
                }
            });

            // Check if UTC button has been ticked.
            $('#showUTCbutton').change(function() {
                if ($(this).is(":checked")) {
                    setCookie("UTC", 'true', 365);
                    for (var i = 0; i < Object.keys(sonde_positions).length; i++) {
                        table.getRow(Object.keys(sonde_positions)[i]).reformat();
                    }
                } else {
                    setCookie("UTC", 'false', 365);
                    for (var i = 0; i < Object.keys(sonde_positions).length; i++) {
                        table.getRow(Object.keys(sonde_positions)[i]).reformat();
                    }
                }
            });

            // Check if settings div has been scrolled.
            $('#scrollsettingsid').scroll(function() {
                if ((document.getElementById("scrollsettingsid").scrollHeight - document.getElementById("scrollsettingsid").scrollTop - document.getElementById("scrollsettingsid").clientHeight) < 1 ) {
                    document.getElementById("downdiv").style.display = "none";
                } else {
                    document.getElementById("downdiv").style.display = "block";
                }
            });

            // Check if pagination selector has been ticked.
            $('#paginationSelector').change(function() {
                setCookie("pagination", this.value, 365);
                table.setPageSize(this.value);
            });

            // Check if cookie exists for entries to display per page in table
            if (getCookie('pagination') != null) {
                pagination_size = parseInt(getCookie('pagination'));
                $('#paginationSelector option[value="'+ getCookie('pagination') +'"]').attr("selected",true);
            } else {
                if (($( window ).width()/$( window ).height()) > 1) {
                    pagination_size = 6;
                    $('#paginationSelector option[value="6"]').attr("selected",true);
                } else {
                    pagination_size = 3;
                    $('#paginationSelector option[value="3"]').attr("selected",true);
                }
            }

            // Create Tabulator table.
            table = new Tabulator("#telem_table", {
                index:"realid",
                //placeholder:"No Sonde Data Available", Does not work when some columns are hidden
                // Split into pages for over 6 entries.
                pagination:"local",
                paginationSize:pagination_size,
                layout:"fitDataFill",
                resizableColumns:"header",
                layoutColumnsOnNewData:true,
                columns:[ //Define Table Columns
                    {title:"SDR", field:"sdr_device_idx", headerSort:true},
                    {title:"Age", field:"age", headerSort:true},
                    {title:"Type", field:"type", headerSort:true},
                    {title:'Freq (MHz)', field:"freq", headerSort:true},
                    {title:"ID", field:"id", width:125, headerSort:true, formatter:function(cell, formatterParams, onRendered){
                        _cell_data = cell.getData();
                        _id = _cell_data.id.replace(/^(DFM|M10|M20|IMET|IMET5|IMET54|MRZ|IMS100|RS11G|MTS01|WXR)-/,"");
                        _sondehub_id = _cell_data.id.replace(/^(DFM|M10|M20|IMET|IMET5|IMET54|MRZ|IMS100|RS11G|MTS01|WXR)-/,"");

                        // Add Sondehub Link
                        _id += "&nbsp;<a href='http://sondehub.org/" + _sondehub_id + "' title='View on Sondehub' target='_blank'>" + "<img src='{{ url_for('static', filename='img/sondehub.png')}}'/>" + "</a>";

                        // Add Radiosondy Link
                        if(_cell_data.aprsid != null){
                            _aprs_id = _cell_data.aprsid.trim();
                            _id += "<a href='https://radiosondy.info/sonde_archive.php?sondenumber=" + _aprs_id + "' title='View on Radiosondy.info' target='_blank'>" + "<img src='{{ url_for('static', filename='img/radiosondy.png')}}'/>" + "</a>";

                        } else {
                            _aprs_id = null;
                        }

                        return _id;
                    }},
                    {title:"Time", field:"datetime", width:180, headerSort:true, formatter:function(cell, formatterParams, onRendered){
                        if (getCookie('UTC') == 'false') {
                            var temp_time = new Date(cell.getValue());
                            var temp_converted = temp_time.toLocaleString(window.navigator.language,{hourCycle:'h23', year:"numeric", month:"2-digit", day:'2-digit', hour:'2-digit',minute:'2-digit', second:'2-digit'});
                            if (temp_converted == "Invalid Date") {                    
                                return;
                            } else {
                                return temp_converted;
                            }                            
                        } else {
                            return cell.getValue();
                        }
                    }
                    },
                    {title:"Frame", field:"frame", headerSort:true},
                    {title:"Latitude", field:"lat", width:80, formatter:'html', headerSort:false},
                    {title:"Longitude", field:"lon", width:80, formatter:'html', headerSort:false},
                    {title:"Alt", field:"alt", headerSort:true, formatter:function(cell, formatterParams, onRendered){
                        if (getCookie('imperial') == 'true') {
                            return (Math.round((cell.getValue()*3.28084) * 10) / 10);
                        } else {
                            return cell.getValue();
                        }
                    }, titleFormatter:function(cell, formatterParams, onRendered){
                        if (getCookie('imperial') == 'true') {
                            return cell.getValue() + " (ft)";
                        } else {
                            return cell.getValue() + " (m)";
                        }
                    }
                    },
                    {title:"Vel", field:"vel_h", headerSort:false, formatter:function(cell, formatterParams, onRendered){
                        if (getCookie('imperial') == 'true') {
                            return (Math.round((cell.getValue()*0.62137) * 10) / 10);
                        } else {
                            return cell.getValue();
                        }
                    }, titleFormatter:function(cell, formatterParams, onRendered){
                        if (getCookie('imperial') == 'true') {
                            return cell.getValue() + " (mph)";
                        } else {
                            return cell.getValue() + " (kph)";
                        }
                    }
                    },
                    {title:"Asc", field:"vel_v", headerSort:false, formatter:function(cell, formatterParams, onRendered){
                        if (getCookie('imperial') == 'true') {
                            return (Math.round((cell.getValue()*196.85) * 10) / 10);
                        } else {
                            return cell.getValue();
                        }
                    }, titleFormatter:function(cell, formatterParams, onRendered){
                        if (getCookie('imperial') == 'true') {
                            return cell.getValue() + " (ft/min)";
                        } else {
                            return cell.getValue() + " (m/s)";
                        }
                    }
                    },
                    {title:"Temp", field:"temp", headerSort:false, formatter:function(cell, formatterParams, onRendered){
                        if (getCookie('imperial') == 'true') {
                            return (Math.round(((cell.getValue()*9/5) + 32) * 10) / 10);
                        } else {
                            return cell.getValue();
                        }
                    }, titleFormatter:function(cell, formatterParams, onRendered){
                        if (getCookie('imperial') == 'true') {
                            return cell.getValue() + " (°F)";
                        } else {
                            return cell.getValue() + " (°C)";
                        }
                    }
                    },
                    {title:"RH (%)", field:"humidity", headerSort:false},
                    {title:"Az (°)", field:"azimuth", headerSort:false},
                    {title:"El (°)", field:"elevation", headerSort:false},
                    {title:"Range", field:"range", headerSort:true, formatter:function(cell, formatterParams, onRendered){
                        if (getCookie('imperial') == 'true') {
                            return (Math.round((cell.getValue()*0.621371) * 10) / 10);
                        } else {
                            return cell.getValue();
                        }
                    }, titleFormatter:function(cell, formatterParams, onRendered){
                        if (getCookie('imperial') == 'true') {
                            return cell.getValue() + " (mi)";
                        } else {
                            return cell.getValue() + " (km)";
                        }
                    }
                    },
                    {title:"SNR (dB)", field:"snr", headerSort:true},
                    {title:"Other", field:"other", width:140, headerSort:false},
                    {title:"Real ID", field:"realid", visible:false}
                ],
                rowContext:function(e, row){
                    e.preventDefault();
                    //Highlight Sonde on map when row selected
                    for (var i = 0; i < Object.keys(sonde_positions).length; i++) {
                        console.log(Object.keys(sonde_positions)[i]);
                        if (Object.keys(sonde_positions)[i] != row['_row']['data']['id'].replace(/(<([^>]+)>)/gi, "")) {
                            sonde_positions[Object.keys(sonde_positions)[i]]['path'].setStyle({
                              color: sonde_positions[Object.keys(sonde_positions)[i]]['colour']
                            });
                            if (sonde_positions[Object.keys(sonde_positions)[i]]['latest_data']['vel_v'] < 0){
                                sonde_positions[Object.keys(sonde_positions)[i]].marker.setIcon(sondeDescentIcons[sonde_positions[Object.keys(sonde_positions)[i]]['colour']]);
                            }else{
                                sonde_positions[Object.keys(sonde_positions)[i]].marker.setIcon(sondeAscentIcons[sonde_positions[Object.keys(sonde_positions)[i]]['colour']]);
                            }
                        }
                    }

                    if (sonde_positions[row['_row']['data']['id'].replace(/(<([^>]+)>)/gi, "")]['path']['options']['color'] != 'white') {
                        selected_sonde = row['_row']['data']['id'].replace(/(<([^>]+)>)/gi, "");
                        sonde_positions[row['_row']['data']['id'].replace(/(<([^>]+)>)/gi, "")]['path'].setStyle({
                          color: 'white'
                        });
                        /*
                        if (sonde_positions[row['_row']['data']['id'].replace(/(<([^>]+)>)/gi, "")]['latest_data']['vel_v'] < 0){
                            sonde_positions[row['_row']['data']['id'].replace(/(<([^>]+)>)/gi, "")].marker.setIcon(sondeDescentIcons['white']);
                        }else{
                            sonde_positions[row['_row']['data']['id'].replace(/(<([^>]+)>)/gi, "")].marker.setIcon(sondeAscentIcons['white']);
                        }
                        */
                    } else {
                        selected_sonde = "";
                        sonde_positions[row['_row']['data']['id'].replace(/(<([^>]+)>)/gi, "")]['path'].setStyle({
                          color: sonde_positions[row['_row']['data']['id'].replace(/(<([^>]+)>)/gi, "")]['colour']
                        });
                        /*
                        if (sonde_positions[row['_row']['data']['id'].replace(/(<([^>]+)>)/gi, "")]['latest_data']['vel_v'] < 0){
                            sonde_positions[row['_row']['data']['id'].replace(/(<([^>]+)>)/gi, "")].marker.setIcon(sondeDescentIcons[sonde_positions[row['_row']['data']['id'].replace(/(<([^>]+)>)/gi, "")]['colour']]);
                        }else{
                            sonde_positions[row['_row']['data']['id'].replace(/(<([^>]+)>)/gi, "")].marker.setIcon(sondeAscentIcons[sonde_positions[row['_row']['data']['id'].replace(/(<([^>]+)>)/gi, "")]['colour']]);
                        }
                        */
                    }

                }
            });

            // Update Tabulator table.
            function updateTelemetryTable(){
                var telem_data = [];

                if (jQuery.isEmptyObject(sonde_positions)){
                    telem_data = [];
                }else{
                    var sonde_id_list = Object.getOwnPropertyNames(sonde_positions).reverse();

                    //for (sonde_id in sonde_id_list){
                    sonde_id_list.forEach( function(sonde_id){
                        var sonde_id_data = Object.assign({},sonde_positions[sonde_id].latest_data);
                        var sonde_id_age = Date.now() - sonde_positions[sonde_id].age;
                        if (sonde_id_age>(1000*autorx_config.rx_timeout)){
                            sonde_id_data.sdr_device_idx = "";
                            sonde_id_data.age = "old";
                            // Remove the LOS line
                            if(sonde_positions[sonde_id].hasOwnProperty("los_path")){
                                sonde_positions[sonde_id].los_path.remove();
                                delete sonde_positions[sonde_id].los_path;
                            }

                        }else{
                            sonde_id_data.age = (sonde_id_age/1000.0).toFixed(0) + " s";
                        }

                        // If we have a station lat/lon/alt set, calculate az/el/range.
                        if (autorx_config.station_lat != 0.0){
                            // There is a station lat/lon set.
                            var _bal = {lat:sonde_id_data.lat, lon:sonde_id_data.lon, alt:sonde_id_data.alt};
                            var _station = {lat:autorx_config.station_lat, lon:autorx_config.station_lon, alt:autorx_config.station_alt};

                            var _look_angles = calculate_lookangles(_station, _bal);

                            sonde_id_data.azimuth = _look_angles.azimuth.toFixed(1);
			    if (_look_angles.elevation >= 10){
                                sonde_id_data.elevation = _look_angles.elevation.toFixed(1);
			    }else{
                                sonde_id_data.elevation = _look_angles.elevation.toFixed(2);
			    }
                            sonde_id_data.range = (_look_angles.range/1000).toFixed(1);
                        } else{
                            // Insert blank data.
                            sonde_id_data.azimuth = "";
                            sonde_id_data.elevation = "";
                            sonde_id_data.range = "";
                        }

                        // Modify some of the fields to fixed point values.

                        // Add Geo ref links to lat/lon fields.
                        temp_lat = "<a href='geo:" + sonde_id_data.lat.toFixed(5) + "," + sonde_id_data.lon.toFixed(5) + "'>" + sonde_id_data.lat.toFixed(5) + "</a>";
                        temp_lon = "<a href='geo:" + sonde_id_data.lat.toFixed(5) + "," + sonde_id_data.lon.toFixed(5) + "'>" + sonde_id_data.lon.toFixed(5) + "</a>";
                        sonde_id_data.lat = temp_lat;
                        sonde_id_data.lon = temp_lon;

                        sonde_id_data.alt = sonde_id_data.alt.toFixed(1);
                        sonde_id_data.vel_v = sonde_id_data.vel_v.toFixed(1);
                        sonde_id_data.vel_h = (sonde_id_data.vel_h*3.6).toFixed(1);


                        // Add a link to HabHub if we have habitat enabled.
                        // if (autorx_config.sondehub_enabled == true) {
                        //     sonde_id_data.id = "<a href='http://sondehub.org/" + sonde_id.replace(/^(DFM|M10|M20|IMET|IMET54|MRZ)-/,"") + "' target='_blank'>" + sonde_id  + "</a>";
                        // // These links are only going to work for Vaisala radiosondes since the APRS callsign is never passed through to the web interface,
                        // // and the APRS callsigns for everything other than RS41s and RS92s is different to the 'full' serials
                        // } else if (autorx_config.aprs_enabled == true && autorx_config.aprs_server == "radiosondy.info") {
                        //     sonde_id_data.id = "<a href='https://radiosondy.info/sonde_archive.php?sondenumber=" + sonde_id + "' target='_blank'>" + sonde_id + "</a>";
                        // } else if (autorx_config.aprs_enabled == true) {
                        //     sonde_id_data.id = "<a href='https://aprs.fi/#!call=" + sonde_id + "&timerange=3600&tail=3600' target='_blank'>" + sonde_id + "</a>";
                        // }

                        sonde_id_data.realid = sonde_id;

                        // Add SNR data, if it exists.
                        if (sonde_id_data.hasOwnProperty('snr')){
                            sonde_id_data.snr = sonde_id_data.snr.toFixed(1);
                        }

                        // Add data into the 'other' field.
                        sonde_id_data.other = "";

                        if(sonde_id_data.hasOwnProperty('rs41_mainboard')){
                            // Only print mainboard type if it's not the 'original' mainboard.
                            if(sonde_id_data.rs41_mainboard !== 'RSM412'){
                                sonde_id_data.other += sonde_id_data.rs41_mainboard + " ";
                            }
                        }

                        // Burst timer for RS41s
                        if (sonde_id_data.hasOwnProperty('bt')){
                            if ((sonde_id_data.bt >= 0) && (sonde_id_data.bt < 65535)) {
                                sonde_id_data.other += "BT " + new Date(sonde_id_data.bt*1000).toISOString().substr(11, 8) + " ";
                            }
                        }
                        if (sonde_id_data.hasOwnProperty('batt')){
                            sonde_id_data.other += sonde_id_data.batt.toFixed(1) + " V";
                        }

                        if (sonde_id_data.hasOwnProperty('aux')){
                            sonde_id_data.type += "-XDATA";
                        }


                        telem_data.push(sonde_id_data);
                    });
                }
                table.updateOrAddData(telem_data);
                // Hide table page navigation if only one page.
                if(table.getPageMax() == 1){
                    $(".tabulator-footer").hide();
                }else{
                    $(".tabulator-footer").show();
                }
            }
            // Invalidate map size to fix problems with elements resizing.
            mymap.invalidateSize();

            var initial_load_complete = false;
            selected_sonde = "";
            $.ajax({ // Get archived data.
                  url: "get_telemetry_archive",
                  dataType: 'json',
                  async: true,
                  success: function(data) {
                    for (sonde_id in data){
                        var telem = data[sonde_id].latest_telem;
                        sonde_positions[sonde_id] = {
                            latest_data: telem,
                            age: 0,
                            colour: colour_values[colour_idx]
                        };
                        // Create markers
                        sonde_positions[sonde_id].path = L.polyline(data[sonde_id].path,{title:telem.id + " Path", color:sonde_positions[sonde_id].colour}).addTo(mymap);

                        if (getCookie('imperial') == 'true'){
                            _alt = (telem.alt*3.28084).toFixed(0) + 'ft   ';
                            _vel_v = (telem.vel_v*3.28084).toFixed(0) + 'ft/s   ';
                            _vel_h = (telem.vel_h*2.23694).toFixed(0) + 'mph  ';
                        } else {
                            _alt = telem.alt.toFixed(0) + 'm   ';
                            _vel_v = telem.vel_v.toFixed(1) + 'm/s   ';
                            _vel_h = (telem.vel_h*3.6).toFixed(0) + 'km/h  ';
                        }

                        sonde_positions[sonde_id].marker = L.marker([telem.lat, telem.lon, telem.alt],{icon: sondeAscentIcons[sonde_positions[sonde_id].colour]})
                            .bindTooltip('<div class="tooltip-container">' + sonde_id + '<div class="tooltip-container" style="color: #005ec1;">' + _alt +  _vel_v +  _vel_h + '</div></div>',{permanent:false, direction:'right', className: 'sondeTooltip', offset: [10,0], interactive: false, opacity: 0.7 })
                            .addTo(mymap);

                        // if(autorx_config.station_lat != 0.0){
                        //     sonde_positions[sonde_id].los_path = L.polyline([],
                        //         {
                        //             color:los_color,
                        //             opacity:los_opacity
                        //         }
                        //     ).addTo(mymap);
                        // }

                        if (telem.vel_v < 0){
                            sonde_positions[sonde_id].marker.setIcon(sondeDescentIcons[sonde_positions[sonde_id].colour]);
                        }

                        colour_idx = (colour_idx+1)%colour_values.length;
                    }
                    updateTelemetryTable();
                    initial_load_complete = true;
                  }
            });

            socket.on('station_update', function(msg) {
                // Station update messages indicate a move of the station location, as updated
                // by a GPS receiver.

                if(initial_load_complete == false){
                    // If we have not completed our initial load of telemetry data, discard this data.
                    return
                }

                // Update the marker position.
                home_marker.setLatLng([msg.lat, msg.lon, msg.alt]).update();

                // Update the autorx_config object, which is used to calculate relative look angles for the telemetry table.
                autorx_config.station_lat = msg.lat;
                autorx_config.station_lon = msg.lon;
                autorx_config.station_alt = msg.alt;

            });

            socket.on('telemetry_event', function(msg) {
                // Telemetry Event messages contain the entire telemetry dictionary, as produced by the SondeDecoder class.
                // This includes the fields: ['frame', 'id', 'datetime', 'lat', 'lon', 'alt', 'temp', 'type', 'freq', 'freq_float']

                if(initial_load_complete == false){
                    // If we have not completed our initial load of telemetry data, discard this data.
                    return
                }

                // Have we seen this sonde before?
                if (sonde_positions.hasOwnProperty(msg.id) == false){
                    // Nope, add a property to the sonde_positions object, and setup markers for the sonde.
                    sonde_positions[msg.id] = {
                        latest_data : msg,
                        age : Date.now(),
                        colour : colour_values[colour_idx]
                    };
                                            // Create markers
                    sonde_positions[msg.id].path = L.polyline([[msg.lat, msg.lon, msg.alt]],{title:msg.id + " Path", color:sonde_positions[msg.id].colour}).addTo(mymap);
                    if (getCookie('imperial') == 'true'){
                            _alt = (msg.alt*3.28084).toFixed(0) + 'ft   ';
                            _vel_v = (msg.vel_v*3.28084).toFixed(0) + 'ft/s   ';
                            _vel_h = (msg.vel_h*2.23694).toFixed(0) + 'mph  ';
                        } else {
                            _alt = msg.alt.toFixed(0) + 'm   ';
                            _vel_v = msg.vel_v.toFixed(1) + 'm/s   ';
                            _vel_h = (msg.vel_h*3.6).toFixed(0) + 'km/h  ';
                        }
                    sonde_positions[msg.id].marker = L.marker([msg.lat, msg.lon, msg.alt],{title:msg.id, icon: sondeAscentIcons[sonde_positions[msg.id].colour]})
                        .bindTooltip('<div class="tooltip-container">' + msg.id + '<div class="tooltip-container" style="color: #005ec1;">' + _alt +  _vel_v +  _vel_h + '</div></div>',{permanent:false, direction:'right', className: 'sondeTooltip', offset: [10,0], interactive: false, opacity: 0.7})
                        .addTo(mymap);

                    // If there is a station location defined, show the path from the station to the sonde.
                    if(autorx_config.station_lat != 0.0){
                        sonde_positions[msg.id].los_path = L.polyline([[autorx_config.station_lat, autorx_config.station_lon],[msg.lat, msg.lon]],
                            {
                                color:los_color,
                                opacity:los_opacity
                            }
                        ).addTo(mymap);
                    }

                    colour_idx = (colour_idx+1)%colour_values.length;
                    // If this is our first sonde since the browser has been opened, follow it.
                    if (Object.keys(sonde_positions).length == 1){
                        sonde_positions[msg.id].following = true;
                    }
                } else {
                    // Yep - update the sonde_positions entry.
                    sonde_positions[msg.id].latest_data = msg;
                    sonde_positions[msg.id].age = Date.now();
                    sonde_positions[msg.id].path.addLatLng([msg.lat, msg.lon, msg.alt]);
                    sonde_positions[msg.id].marker.setLatLng([msg.lat, msg.lon, msg.alt]).update();
                    if (getCookie('imperial') == 'true'){
                            _alt = (msg.alt*3.28084).toFixed(0) + 'ft   ';
                            _vel_v = (msg.vel_v*3.28084).toFixed(0) + 'ft/s   ';
                            _vel_h = (msg.vel_h*2.23694).toFixed(0) + 'mph  ';
                        } else {
                            _alt = msg.alt.toFixed(0) + 'm   ';
                            _vel_v = msg.vel_v.toFixed(1) + 'm/s   ';
                            _vel_h = (msg.vel_h*3.6).toFixed(0) + 'km/h  ';
                        }
                    sonde_positions[msg.id].marker.setTooltipContent('<div class="tooltip-container">' + msg.id + '<div class="tooltip-container" style="color: #005ec1;">' + _alt +  _vel_v +  _vel_h +'</div></div>');

                    if (msg.vel_v < 0){
                        if (selected_sonde == msg.id) {
                            sonde_positions[msg.id].marker.setIcon(sondeDescentIcons['white']);
                        } else {
                            sonde_positions[msg.id].marker.setIcon(sondeDescentIcons[sonde_positions[msg.id].colour]);
                        }
                    }else{
                        if (selected_sonde == msg.id) {
                            sonde_positions[msg.id].marker.setIcon(sondeAscentIcons['white']);
                        } else {
                            sonde_positions[msg.id].marker.setIcon(sondeAscentIcons[sonde_positions[msg.id].colour]);
                        }
                    }

                    if(autorx_config.station_lat != 0.0){
                        if(sonde_positions[msg.id].hasOwnProperty("los_path")){
                            sonde_positions[msg.id].los_path.setLatLngs([[autorx_config.station_lat, autorx_config.station_lon],[msg.lat, msg.lon]]);
                        } else {
                            sonde_positions[msg.id].los_path = L.polyline([[autorx_config.station_lat, autorx_config.station_lon],[msg.lat, msg.lon]],
                            {
                                color:los_color,
                                opacity:los_opacity
                            }
                            ).addTo(mymap);
                        }
                    }
                }

                // Update the telemetry table display
                //updateTelemetryText();
                updateTelemetryTable();

                // Are we currently following any other sondes?
                if (sonde_currently_following == "none"){
                    // If not, follow this one!
                    sonde_currently_following = msg.id;
                }

                // Is sonde following enabled?
                if (document.getElementById("sondeAutoFollow").checked == true){
                    // If we are currently following this sonde, snap the map to it.
                    if (msg.id == sonde_currently_following){
                            mymap.panTo([msg.lat,msg.lon], { duration: 2.5, easeLinearity: 0.9 });
                    }
                }
            });


            // Sonde-Following Logic. May need to adjust timeouts.
            var sonde_follow_timeout = 30000; // 30 Seconds - reasonable timeout.
            // Every X seconds, check if the currently followed sonde is still getting regular data.
            // If not, clear the currently_following flag to allow another sonde to be auto tracked.
            window.setInterval(function () {
                if (sonde_currently_following == "none"){
                    return;
                }
                var now_time = Date.now();
                if ( (now_time-sonde_positions[sonde_currently_following].age) > sonde_follow_timeout){
                    sonde_currently_following = "none";
                }
            }, sonde_follow_timeout);


            // Update telemetry table every second (this is mainly to update the age field)
            window.setInterval(function(){
                updateTelemetryTable();
            }, 1000);

            // Tell program we are connected and ready for data.
            socket.on('connect', function() {
                socket.emit('client_connected', {data: 'I\'m connected!'});
            });

            // Function to change table columns visible.
            $(document).on('change', 'form input', function() {
                var checked = $(this).is(":checked");

                if (checked == false) {
                  var cookiesend = 'false';
                } else {
                  var cookiesend = 'true';
                }

                var index = $(this).attr("class");

                // Set cookie for columns to show in future.
                setCookie("col" + index, cookiesend, 365);

                // Update Tabulator table with selected columns visible.
                if(checked) {
                    switch(index) {
                        case "0":
                            table.showColumn("sdr_device_idx");
                            break;
                        case "1":
                            table.showColumn("age");
                            break;
                        case "2":
                            table.showColumn("type");
                            break;
                        case "3":
                            table.showColumn("freq");
                            break;
                        case "4":
                            table.showColumn("id");
                            break;
                        case "5":
                            table.showColumn("datetime");
                            break;
                        case "6":
                            table.showColumn("frame");
                            break;
                        case "7":
                            table.showColumn("lat");
                            break;
                        case "8":
                            table.showColumn("lon");
                            break;
                        case "9":
                            table.showColumn("alt");
                            break;
                        case "10":
                            table.showColumn("vel_h");
                            break;
                        case "11":
                            table.showColumn("vel_v");
                            break;
                        case "12":
                            table.showColumn("temp");
                            break;
                        case "13":
                            table.showColumn("humidity");
                            break;
                        case "14":
                            table.showColumn("azimuth");
                            break;
                        case "15":
                            table.showColumn("elevation");
                            break;
                        case "16":
                            table.showColumn("range");
                            break;
                        case "17":
                            table.showColumn("snr");
                            break;
                        case "18":
                            table.showColumn("other");
                            break;
                    }
                    table.redraw();
                } else {
                    switch(index) {
                        case "0":
                            table.hideColumn("sdr_device_idx");
                            break;
                        case "1":
                            table.hideColumn("age");
                            break;
                        case "2":
                            table.hideColumn("type");
                            break;
                        case "3":
                            table.hideColumn("freq");
                            break;
                        case "4":
                            table.hideColumn("id");
                            break;
                        case "5":
                            table.hideColumn("datetime");
                            break;
                        case "6":
                            table.hideColumn("frame");
                            break;
                        case "7":
                            table.hideColumn("lat");
                            break;
                        case "8":
                            table.hideColumn("lon");
                            break;
                        case "9":
                            table.hideColumn("alt");
                            break;
                        case "10":
                            table.hideColumn("vel_h");
                            break;
                        case "11":
                            table.hideColumn("vel_v");
                            break;
                        case "12":
                            table.hideColumn("temp");
                            break;
                        case "13":
                            table.hideColumn("humidity");
                            break;
                        case "14":
                            table.hideColumn("azimuth");
                            break;
                        case "15":
                            table.hideColumn("elevation");
                            break;
                        case "16":
                            table.hideColumn("range");
                            break;
                        case "17":
                            table.hideColumn("snr");
                            break;
                        case "18":
                            table.hideColumn("other");
                            break;
                }
                table.redraw();
              }
            });

            // Runs once at page load to set which Tabulator columns to show/hide per set cookies
            for (i = 0; i < 19; i++) {
                var show = getCookie("col"+i);
                if (show == 'false') {
                    document.getElementById("checkbox" + i).checked = false;
                    switch(i) {
                        case 0:
                            table.hideColumn("sdr_device_idx");
                            break;
                        case 1:
                            table.hideColumn("age");
                            break;
                        case 2:
                            table.hideColumn("type");
                            break;
                        case 3:
                            table.hideColumn("freq");
                            break;
                        case 4:
                            table.hideColumn("id");
                            break;
                        case 5:
                            table.hideColumn("datetime");
                            break;
                        case 6:
                            table.hideColumn("frame");
                            break;
                        case 7:
                            table.hideColumn("lat");
                            break;
                        case 8:
                            table.hideColumn("lon");
                            break;
                        case 9:
                            table.hideColumn("alt");
                            break;
                        case 10:
                            table.hideColumn("vel_h");
                            break;
                        case 11:
                            table.hideColumn("vel_v");
                            break;
                        case 12:
                            table.hideColumn("temp");
                            break;
                        case 13:
                            table.hideColumn("humidity");
                            break;
                        case 14:
                            table.hideColumn("azimuth");
                            break;
                        case 15:
                            table.hideColumn("elevation");
                            break;
                        case 16:
                            table.hideColumn("range");
                            break;
                        case 17:
                            table.hideColumn("snr");
                            break;
                        case 18:
                            table.hideColumn("other");
                            break;
                    }
                } else if (show == 'true') {
                    document.getElementById("checkbox" + i).checked = true;
                } else {
                    if ($( window ).width() > 1200) {
                        document.getElementById("checkbox" + i).checked = true;
                    } else { // If no cookies are set on mobile device show limited number for better experience.
                        if ([1,4,9,16].includes(i)) {
                            setCookie("col" + i, 'true', 365);
                            document.getElementById("checkbox" + i).checked = true;
                        }
                        if ([0,2,3,5,6,7,8,10,11,12,13,14,15,17,18].includes(i)) {
                            setCookie("col" + i, 'false', 365);
                            document.getElementById("checkbox" + i).checked = false;
                            switch(i) {
                                case 0:
                                    table.hideColumn("sdr_device_idx");
                                    break;
                                case 1:
                                    table.hideColumn("age");
                                    break;
                                case 2:
                                    table.hideColumn("type");
                                    break;
                                case 3:
                                    table.hideColumn("freq");
                                    break;
                                case 4:
                                    table.hideColumn("id");
                                    break;
                                case 5:
                                    table.hideColumn("datetime");
                                    break;
                                case 6:
                                    table.hideColumn("frame");
                                    break;
                                case 7:
                                    table.hideColumn("lat");
                                    break;
                                case 8:
                                    table.hideColumn("lon");
                                    break;
                                case 9:
                                    table.hideColumn("alt");
                                    break;
                                case 10:
                                    table.hideColumn("vel_h");
                                    break;
                                case 11:
                                    table.hideColumn("vel_v");
                                    break;
                                case 12:
                                    table.hideColumn("temp");
                                    break;
                                case 13:
                                    table.hideColumn("humidity");
                                    break;
                                case 14:
                                    table.hideColumn("azimuth");
                                    break;
                                case 15:
                                    table.hideColumn("elevation");
                                    break;
                                case 16:
                                    table.hideColumn("range");
                                    break;
                                case 17:
                                    table.hideColumn("snr");
                                    break;
                                case 18:
                                    table.hideColumn("other");
                                    break;
                            }
                        }
                    }
                }
            }
            table.redraw();
        });

        // Function to open/close left log menu along with adjusting other elements so they render correctly.
        function changeNav() {
            if (getCookie('dark') == 'false') {
                $('#log-tray').css('color', 'black');
            } else if (getCookie('dark') == 'true') {
                $('#log-tray').css('color', 'white');
            } else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
                $('#log-tray').css('color', 'white');
            } else {
                $('#log-tray').css('color', 'black');
            }
            var x = document.getElementById("closebtn");
            var y = document.getElementById('mapid');
            if (document.getElementById("mySidenav").style.width == "0px" || document.getElementById("mySidenav").style.width == 0) {
                var myDiv = document.getElementById('sidenavtable');
                myDiv.scrollTop = 0;
                if ((window.innerWidth/window.innerHeight) > 1) { // 350px wide on desktop.
                    x.style.display = "none";
                    if (getCookie('map') == true || document.getElementById("showmapbutton").checked == true) {
                        y.style.display = "block";
                    }
                    document.getElementById("mySidenav").style.width = "350px";
                    document.getElementById("main").style.marginLeft = "350px";
                    document.getElementById("mySidenav").style.borderRadius = "0px 25px 25px 0px";
                    mymap.invalidateSize();
                    setTimeout(scan_chart_obj.resize,500);
                } else { // Fullsize on mobile.
                    x.style.display = "block";
                    y.style.display = "none";
                    document.getElementById("mySidenav").style.width = "100%";
                    document.getElementById("main").style.marginLeft = "0";
                    document.getElementById("mySidenav").style.borderRadius = "0px";
                }
            } else {
                x.style.display = "none";
                if (getCookie('map') == true || document.getElementById("showmapbutton").checked == true) {
                    y.style.display = "block";
                }
                document.getElementById("mySidenav").style.width = 0;
                document.getElementById("main").style.marginLeft = 0;
                mymap.invalidateSize();
                setTimeout(scan_chart_obj.resize,500);
            }
        }

        // Function to open/close right settings menu along with adjusting other elements so they render correctly.
        function changeSettings() {
            var y = document.getElementById('mapid');
            if (document.getElementById("mySettings").style.width == "0px" || document.getElementById("mySettings").style.width == 0) {
                if ((window.innerWidth/window.innerHeight) > 1) { // 350px wide on desktop.
                    if (getCookie('map') == true || document.getElementById("showmapbutton").checked == true) {
                        y.style.display = "block";
                    }
                    document.getElementById("mySettings").style.width = "350px";
                    document.getElementById("main").style.marginRight = "350px";
                    document.getElementById("mySettings").style.borderRadius = "25px 0px 0px 25px";
                    mymap.invalidateSize();
                    setTimeout(scan_chart_obj.resize,500);
                    setTimeout(showDown,500);
                } else { // Fullsize on mobile.
                    y.style.display = "none";
                    document.getElementById("mySettings").style.width = "100%";
                    document.getElementById("main").style.marginRight = "0";
                    document.getElementById("mySettings").style.borderRadius = "0px";
                }
            } else {
                if (getCookie('map') == true || document.getElementById("showmapbutton").checked == true) {
                    y.style.display = "block";
                }
                document.getElementById("mySettings").style.width = 0;
                document.getElementById("main").style.marginRight = 0;
                mymap.invalidateSize();
                setTimeout(scan_chart_obj.resize,500);
                setTimeout(showDown,500);
            }
        }

        function showDown () {
            if ((document.getElementById("scrollsettingsid").scrollHeight - document.getElementById("scrollsettingsid").scrollTop - document.getElementById("scrollsettingsid").clientHeight) < 1 ) {
                document.getElementById("downdiv").style.display = "none";
            } else {
                document.getElementById("downdiv").style.display = "block";
            }
        }

        // Show/hide map on button press and update cookies.
        function showMap(element) {
           if (element.checked == false) {
             document.getElementById("mapid").style.display = "none";
             setCookie("map", 'false', 365);
           } else {
             document.getElementById("mapid").style.display = "block";
             setCookie("map", 'true', 365);
             mymap.invalidateSize();
           }
        }

        // Show/hide scan chart on button press and update cookies.
        function showScan(element) {
           if (element.checked == false) {
             document.getElementById("scanid").style.display = "none";
             setCookie("scan", 'false', 365);
             mymap.invalidateSize();
           } else {
             document.getElementById("scanid").style.display = "block";
             setCookie("scan", 'true', 365);
             mymap.invalidateSize();
             redraw_scan_chart();
             setTimeout(scan_chart_obj.resize,500);
           }
        }

        // Enable/disable auto follow on button press and update cookies.
        function autoFollow(element) {
           if (element.checked == false) {
             setCookie("follow", 'false', 365);
           } else {
             setCookie("follow", 'true', 365);
           }
        }

        // Show/hide table on button press and update cookies.
        function showTable(element) {
           if (element.checked == false) {
             document.getElementById("tableid").style.display = "none";
             setCookie("table", 'false', 365);
           } else {
             document.getElementById("tableid").style.display = "block";
             setCookie("table", 'true', 365);
           }
        }

        // Set given cookie name and value.
        function setCookie(name,value) {
            localStorage.setItem(name, value);
        }

        // Return cookie value given name.
        function getCookie(name) {
            return localStorage.getItem(name);
        }

        // Reset specific cookie.
        function eraseCookie(name) {
            localStorage.removeItem(name);
        }

        // Reset all cookies.
        function deleteAllCookies() {
            localStorage.clear();
            location.reload();
        }

        // When the user clicks on the button, open the modal
        function openModal() {
          document.getElementById("myModal").style.display = "block";
          changeSettings()
          if (getCookie("password") === null) {} else {
            verify_password();
          }
        }

        // When the user clicks on close button, close the modal
        function closeModal() {
          document.getElementById("myModal").style.display = "none";
          $('#password-input').val('');
        }

        // When the user clicks anywhere outside of the modal, close it
        $(window).click(function(e) {
            if (e.target == document.getElementById("myModal")) {
                document.getElementById("myModal").style.display = "none";
                $('#password-input').val('');
            }
        });

        let vh = window.innerHeight * 0.01;

        document.documentElement.style.setProperty('--vh', `${vh}px`);
    </script>
</head>
<body>
    <!-- Wrapper for entire body to ensure flex works -->
    <div class="wrapper">
        <!-- Wrapper for log sidebar -->
        <div id="mySidenav" class="sidenav">
            <div class="headerdiv">
            <a href="javascript:void(0)" class="closebtn" id="closebtn" onclick="changeNav()">&#10006;</a>
            <img src="{{ url_for('static', filename='img/autorx_logo.png') }}" alt="Radiosonde Auto-RX Button">
            <h2>Log</h2>
            </div>
            <div class="sidenavtable" id="sidenavtable">
                <table style="width:100%" id="log_data">
                    <tbody>
                    </tbody>
                </table>
            </div>
        </div>

    <!-- Wrapper for settings sidebar -->
    <div id="mySettings" class="settings">
        <a href="javascript:void(0)" class="closebtn2" id="closebtn2" onclick="changeSettings()">&#10006;</a>
        <h1 style="color: white; text-align: center; margin: -0.25em;">Settings</h1>
        <div class="scrollsettings" id="scrollsettingsid" style="margin-top: 20px;">
           <h2 style="display:inline; vertical-align:middle; margin-left: 35px; margin-bottom: 0.3em;">Table Options</h2>
              <form>
                  <input type="checkbox" class="0" id="checkbox0" checked>
                  <label> SDR</label><br>
                  <input type="checkbox" class="1" id="checkbox1" checked>
                  <label> Age</label><br>
                  <input type="checkbox" class="2" id="checkbox2" checked>
                  <label> Type</label><br>
                  <input type="checkbox" class="3" id="checkbox3" checked>
                  <label> Frequency</label><br>
                  <input type="checkbox" class="4" id="checkbox4" checked>
                  <label> ID</label><br>
                  <input type="checkbox" class="5" id="checkbox5" checked>
                  <label> Time</label><br>
                  <input type="checkbox" class="6" id="checkbox6" checked>
                  <label> Frame</label><br>
                  <input type="checkbox" class="7" id="checkbox7" checked>
                  <label> Latitude</label><br>
                  <input type="checkbox" class="8" id="checkbox8" checked>
                  <label> Longitude</label><br>
                  <input type="checkbox" class="9" id="checkbox9" checked>
                  <label> Altitude</label><br>
                  <input type="checkbox" class="10" id="checkbox10" checked>
                  <label> Velocity</label><br>
                  <input type="checkbox" class="11" id="checkbox11" checked>
                  <label> Ascent Rate</label><br>
                  <input type="checkbox" class="12" id="checkbox12" checked>
                  <label> Temperature</label><br>
                  <input type="checkbox" class="13" id="checkbox13" checked>
                  <label> Humidity</label><br>
                  <input type="checkbox" class="14" id="checkbox14" checked>
                  <label> Azimuth</label><br>
                  <input type="checkbox" class="15" id="checkbox15" checked>
                  <label> EI</label><br>
                  <input type="checkbox" class="16" id="checkbox16" checked>
                  <label> Range</label><br>
                  <input type="checkbox" class="17" id="checkbox17" checked>
                  <label> SNR</label><br>
                  <input type="checkbox" class="18" id="checkbox18" checked>
                  <label> Other</label><br><br>
              </form>
              <div style="margin-left:40px;">
                  <h2 style="display:inline;vertical-align:middle;">Show Table</h2>
                  &nbsp;
                  <div style="display:inline;vertical-align:middle;">
                  <label class="switch">
                    <input type="checkbox" onchange="showTable(this)" id="showtablebutton">
                    <span class="slider round"></span>
                  </label>
                  </div>
                  <br>
                  <br>
                  <h2 style="display:inline;vertical-align:middle;">Show Scan Plot</h2>
                  &nbsp;
                  <div style="display:inline;vertical-align:middle;">
                  <label class="switch">
                    <input type="checkbox" onchange="showScan(this)" id="showscanbutton">
                    <span class="slider round"></span>
                  </label>
                  </div>
                  <br>
                  <br>
                  <h2 style="display:inline;vertical-align:middle;">Show Map</h2>
                  &nbsp;
                  <div style="display:inline;vertical-align:middle;">
                  <label class="switch">
                    <input type="checkbox" onchange="showMap(this)" id="showmapbutton">
                    <span class="slider round"></span>
                  </label>
                  </div>
                  <br>
                  <br>
                  <h2 style="display:inline;vertical-align:middle;">Dark Mode</h2>
                  &nbsp;
                  <div style="display:inline;vertical-align:middle;">
                  <label class="switch">
                    <input type="checkbox" id="showdarkbutton">
                    <span class="slider round"></span>
                  </label>
                  </div>
                  <br>
                  <br>
                  <h2 style="display:inline;vertical-align:middle;">Show UTC Time</h2>
                  &nbsp;
                  <div style="display:inline;vertical-align:middle;">
                  <label class="switch">
                    <input type="checkbox" id="showUTCbutton">
                    <span class="slider round"></span>
                  </label>
                  </div>
                  <br>
                  <br>
                  <h2 style="display:inline;vertical-align:middle;">Set Pagination Size</h2>
                  &nbsp;
                  <div style="display:inline;vertical-align:middle;">
                  <select id="paginationSelector" style="font-size: 1.2rem;">
                    <option value="1">One</option>
                    <option value="2">Two</option>
                    <option value="3">Three</option>
                    <option value="4">Four</option>
                    <option value="5">Five</option>
                    <option value="6">Six</option>
                    <option value="7">Seven</option>
                    <option value="8">Eight</option>
                    <option value="9">Nine</option>
                    <option value="10">Ten</option>
                </select>
                  </div>
                  <br>
                  <br>
                  <h2 style="display:inline;vertical-align:middle;">Follow Sonde</h2>
                  &nbsp;
                  <div style="display:inline;vertical-align:middle;">
                  <label class="switch">
                    <input type="checkbox" onchange="autoFollow(this)" id="sondeAutoFollow">
                    <span class="slider round"></span>
                  </label>
                  </div>
                  <br>
                  <br>
                  <h2 style="display:inline;vertical-align:middle;">Show Imperial Units</h2>
                  &nbsp;
                  <div style="display:inline;vertical-align:middle;">
                  <label class="switch">
                    <input type="checkbox" id="showimperialbutton">
                    <span class="slider round"></span>
                  </label>
                  </div>
                  <br>
                  <br>
                  <h2 style="display:inline;vertical-align:middle;">Show Software Version</h2>
                  &nbsp;
                  <div style="display:inline;vertical-align:middle;">
                  <label class="switch">
                    <input type="checkbox" id="showversionbutton">
                    <span class="slider round"></span>
                  </label>
                  </div>
                  <br>
                  <br>
                  <h2 style="display:inline;vertical-align:middle;">Live KML</h2>
                  &nbsp;
                  <div style="display:inline;vertical-align:middle;">
                      <button onclick="window.location.href='rs.kml'">SHOW</button>
                  </div>
                  <br>
                  <br>
                  <h2 style="display:inline;vertical-align:middle;">Reset Page</h2>
                  &nbsp;
                  <div style="display:inline;vertical-align:middle;">
                    <button onclick="deleteAllCookies()">RESET</button>
                  </div>
                  <br>
                  <br>
                  <h2 style="display:inline;vertical-align:middle;">Controls</h2>
                  &nbsp;
                  <div style="display:inline;vertical-align:middle;">
                    <button id="open-controls" onclick="openModal()">OPEN</button>
                  </div>
                  <br>
                  <br>
                  <h2 style="display:inline;vertical-align:middle;">Historical View</h2>
                  &nbsp;
                  <div style="display:inline;vertical-align:middle;">
                    <button onclick="window.location.href='historical.html'">OPEN</button>
                  </div>
                  <br>
                  <br>
                  <br>
            </div>
        </div>
        <div id="downdiv">
            <i class="icon-angle-down" style="font-size:60px;opacity:1;"></i>
        </div>
    </div>

    <!-- Wrapper for main screen -->
    <div id="main" onload="loadMap();">
        <div>
            <span style="font-size:3vh;font-size:calc(var(--vh, 1vh) * 3);cursor:pointer;" onclick="changeNav()"><span id="log-tray">&#9776;</span> Radiosonde Auto-RX <span id="currentversion" style="white-space:nowrap"></span></span>
        </div>
        <span style="font-size:2vh;font-size:calc(var(--vh, 1vh) * 2);" id="footertext"></span>
        <p style="font-size:2vh;font-size:calc(var(--vh, 1vh) * 2);">Station: <span id="station_callsign">???</span></p>
        <p style="font-size:2vh;font-size:calc(var(--vh, 1vh) * 2);">Tasking: <span id="task_status"></span></p>
        <div id="tableid">
            <div id="telem_table"></div>
        </div>
        <div id="scanid">
            <h2>Scan Results</h2>
            <div id='scan_results'>No scan data yet...</div>
            <div id="scan_chart" style="width:100%;"></div>
        </div>
        <br>
        <div id="mapid"></div>
        <i id="myBtn1" onclick="changeSettings()" class="icon-cog" style="font-size:4vh;font-size:calc(var(--vh, 1vh) * 4);"></i>
        <a href="historical.html" id="myBtn2"><i class="icon-history" style="font-size:4vh;font-size:calc(var(--vh, 1vh) * 4);"></i></a>
    </div>

    <!-- Wrapper for advanced control modal -->
    <div id="myModal" class="modal">
      <div class="modal-content">
        <div class="modal-header">
          <span class="close" onclick="closeModal()">&times;</span>
          <h2>Advanced Controls</h2>
        </div>
        <div class="modal-body">
          <div id="password-field">
            <span id="password-header"><h2>No Password Entered</h2></span>
            <input style="display:inline;vertical-align:middle;" type="text" id="password-input" placeholder="Password" >
            <div style="display:inline;vertical-align:middle;">
              <button id="verify-password" onclick="verify_password();$('#password-input').val('');">Submit</button>
            </div>
          </div>
          <div id="controls" style="visibility:hidden;display:none;">
            <h2>Decoder Control</h2>
            <p>Start Decoder</p>
            <input style="display:inline;vertical-align:middle;" type="text" id="frequency-input" placeholder="Frequency (MHz)">
            <select style="display:inline;vertical-align:middle;" class="control" id="sonde-type-select">
                <option value="RS41" selected>RS41</option>
                <option value="RS92">RS92</option>
                <option value="DFM">DFM</option>
                <option value="M10">M10</option>
                <option value="M20">M20</option>
                <option value="LMS6">LMS6 (400 MHz)</option>
                <option value="MK2LMS">LMS6 (1680 MHz)</option>
                <option value="IMET">iMet-4</option>
                <option value="IMET5">iMet-50/54</option>
                <option value="MEISEI">iMS-100</option>
                <option value="MRZ">MRZ-H1</option>
                <option value="MTS01">MTS01</option>
                <option value="WXR301">WXR301</option>
            </select>
            <div style="display:inline;vertical-align:middle;">
                <button id="start-decoder" onclick="start_decoder();">Start</button>
            </div>
            <br>
            <p>Stop Decoder</p>
            <select style="display:inline;vertical-align:middle;" class="control" id="stop-frequency-select">
                <option value="0" disabled selected>No Decoders</option>
            </select>
            <div style="display:inline;vertical-align:middle;">
                <button id="stop-decoder" onclick="stop_decoder();">Stop</button>
            </div>
            <h2>Scanner Control</h2>
            <p>Scanner</p>
            <div style="display:inline;vertical-align:middle;">
                <button id="enable-scanner" onclick="enable_scanner();">Enable</button>
            </div>
            <div style="display:inline;vertical-align:middle;">
                <button id="disable-scanner" onclick="disable_scanner();">Disable</button>
            </div>
          </div>
        </div>
      </div>
    </div>
</div>
</body>
</html>
