<script src="script/chart.js"></script>
<div class="ui stackable grid">
    <div class="ten wide column serverstatusWrapper">
        <div id="serverstatus" class="ui statustab inverted segment">
            <h1 class="ui header" style="margin-top: 1em; margin-left: 0.4em; padding-bottom: 1em;">
                <i id="rpStatusIcon" class="loading spinner icon"></i>
                <div class="content">
                    <span id="statusTitle">Loading</span>
                    <div class="sub header" id="statusText">Checking server status</div>
                </div>
            </h1>
            <div class="dot-container">
                <div class="dot"></div>
                <div class="dot"></div>
                <div class="dot"></div>
                <div class="dot"></div>
            </div>
        </div>
    </div>
    <div class="six wide column statisticWrapper">
        <div class="ui greybackground statustab segment">
            <h5 class="ui header">
                <i class="exchange icon"></i>
                <div class="content">
                    <span id="summaryTotalCount"></span> <small>Req. Today</small>
                    <div class="sub header" style="margin-top: 0.4em;">
                    <i class="green circle check icon"></i> <span id="summarySuccCount"></span>
                        / <i class="red red exclamation circle icon"></i> <span id="summaryErrCount"></span>
                    </div>
                </div>
            </h5>
            <div class="ui divider"></div>
            <h5 class="ui header">
                <i class="arrows alternate horizontal icon"></i>
                <div class="content">
                    <span id="forwardtype"></span>
                    <div class="sub header" id="forwardtypeList">

                    </div>
                </div>
            </h5>
            <div class="ui divider"></div>
            <h5 class="ui header">
                <i class="map marker alternate icon"></i>
                <div class="content">
                    <span id="country"></span>
                    <div class="sub header" id="countryList">

                    </div>
                </div>
            </h5>
        </div>
    </div>
</div>

<div id="networkActWrapper" class="standardContainer" style="position: relative; margin-top: 1em;">
    <canvas id="networkActivity"></canvas>
</div>
<div id="networkActivityPlaceHolder">
    <p style="opacity: 0.5;"><i class="ui pause icon"></i> Graph Render Paused</p>
</div>
<br>
<div class="standardContainer">
    <h4>Basic Settings</h4>
    <p>Inbound Port (Port to be proxied)</p>
    <div class="ui action fluid notloopbackOnly input">
        <input type="text" id="incomingPort" placeholder="Incoming Port" value="80">
        <button class="ui basic green notloopbackOnly button" onclick="handlePortChange();">Apply</button>
    </div>
    <br>
    <div id="tls" class="ui toggle notloopbackOnly checkbox">
        <input type="checkbox">
        <label>Use TLS to serve proxy request</label>
    </div>
    <br>
    <div id="redirect" class="ui toggle notloopbackOnly checkbox" style="margin-top: 0.6em;">
        <input type="checkbox">
        <label>Force redirect HTTP request to HTTPS<br>
            <small>(Only apply when listening port is not 80)</small></label>
    </div>
    <br><br>
    <button id="startbtn" class="ui teal button" onclick="startService();">Start Service</button>
    <button id="stopbtn" class="ui red notloopbackOnly disabled button" onclick="stopService();">Stop Service</button>
    <div id="rploopbackWarning" class="ui segment" style="display:none;">
        <b><i class="yellow warning icon"></i> Loopback Routing Warning</b><br>
        <small>This management interface is a loopback proxied service. <br>If you want to shutdown the reverse proxy server, please remove the proxy rule for the management interface and refresh.</small>
    </div>
    <div class="ui divider"></div>
    <div class="">
    <h4>Statistic Overview</h4>
    <div class="ui two column stackable grid">
        <div class="column">
        <p>Visitor Counts</p>
        <table class="ui unstackable inverted celled table">
            <thead>
            <tr>
                <th>Country ISO Code</th>
                <th>Unique Visitors</th>
            </tr>
            </thead>
            <tbody id="countryCodetable">
                <tr>
                    <td colspan="2">No Data</td>
                </tr>
            </tbody>
        </table>
        </div>
        <div class="column">
        <p>Proxy Request Types</p>
        <table class="ui unstackable inverted celled table">
            <thead>
            <tr>
                <th>Proxy Type</th>
                <th>Count</th>
            </tr>
            </thead>
            <tbody id="forwardTypeTable">
                <tr>
                    <td colspan="2">No Data</td>
                </tr>
            </tbody>
        </table>
        </div>
    </div>
    </div>
    <br>
    <button class="ui right floated basic button" onclick="getDailySummaryDetails();"><i class="green refresh icon"></i> Refresh</button>
    <br><br>
</div>
<script>
    let loopbackProxiedInterface = false;
    //Initial the start stop button if this is reverse proxied
    $.get("/api/proxy/requestIsProxied", function(data){
        if (data == true){
            //This management interface is reverse proxied by itself
            //do not allow turning off the proxy
            $(".notloopbackOnly").addClass("disabled");
            loopbackProxiedInterface = true;
            $("#rploopbackWarning").show();
        }   
    });

    //Get the latest server status from proxy server
    function initRPStaste(){
        $.get("/api/proxy/status", function(data){
            if (data.Running == true){
                $("#startbtn").addClass("disabled");
                if (!loopbackProxiedInterface){
                    $("#stopbtn").removeClass("disabled");
                }
                $("#serverstatus").addClass("green");
                $("#statusTitle").text("Online");
                $("#rpStatusIcon").attr("class", "green circle check icon");
                $("#statusText").text("Serving request on port: " + data.Option.Port);
            }else{
                $("#startbtn").removeClass("disabled");
                $("#stopbtn").addClass("disabled");
                $("#statusTitle").text("Offline");
                $("#rpStatusIcon").attr("class", "black circle times icon")
                $("#statusText").text("Reverse proxy server is offline");
                $("#serverstatus").removeClass("green");
            }
            $("#incomingPort").val(data.Option.Port);
        });
        
    }

    function abbreviateNumber(value) {
        var newValue = value;
        var suffixes = ["", "k", "m", "b", "t"];
        var suffixNum = 0;
        while (newValue >= 1000 && suffixNum < suffixes.length - 1) {
            newValue /= 1000;
            suffixNum++;
        }
        if (value > 1000){
            newValue = newValue.toFixed(2);
        }
        
        return newValue + suffixes[suffixNum];
    }

    function getDailySummaryDetails(){
        function sortObjectByValue(obj) {
            // Convert object to array of [key, value] pairs
            const entries = Object.entries(obj);
            
            // Sort array based on value of each pair
            entries.sort((a, b) => {
                return b[1] - a[1];
            });
            
            // Convert sorted array back to object
            const sortedObj = {};
            for (const [key, value] of entries) {
                sortedObj[key] = value;
            }
            
            return sortedObj;
        }

        $.get("/api/stats/countries", function(data){
            data = sortObjectByValue(data);
            $("#country").html((Object.keys(data)[0])?Object.keys(data)[0]:"No Data");
            $("#countryList").html(`
            <div>
                ${(Object.keys(data)[1])?Object.keys(data)[1]:"-"}<br>
                ${(Object.keys(data)[2])?Object.keys(data)[2]:"-"}
            </div>
            `);

            //populate the table
            $("#countryCodetable").html("");
            for (const [key, value] of Object.entries(data)) {
                var countryName = getCountryName(key);
                if (countryName == ""){
                    countryName = "LAN"
                }
                $("#countryCodetable").append(`<tr>
                    <td>${key} (${countryName})</td>
                    <td>${value}</td>
                </tr>`);
            }

            if (Object.keys(data).length == 0){
                $("#countryCodetable").append(`<tr>
                    <td colspan="2"><i class="ui green circle check icon"></i> No Data</td>
                </tr>`);
            }
            
        });

        //Filter forward type
        function fft(ft){
            if (ft.indexOf("-") >= 0){
                ft = ft.replace("-", " (");
                ft = ft + ")";
            }

            ft = ft.charAt(0).toUpperCase() + ft.slice(1);
            return ft;
        }

        $.get("/api/stats/summary", function(data){
            data = sortObjectByValue(data.ForwardTypes);
            $("#forwardtype").html((Object.keys(data)[0])?fft(Object.keys(data)[0]) + ": " + abbreviateNumber(data[Object.keys(data)[0]]):"No Data");
            $("#forwardtypeList").html(`
            <div>
                ${(Object.keys(data)[1])?fft(Object.keys(data)[1]) + ": " + abbreviateNumber(data[Object.keys(data)[1]]):"-"}<br>
                ${(Object.keys(data)[2])?fft(Object.keys(data)[2]) + ": " + abbreviateNumber(data[Object.keys(data)[2]]):"-"}
            </div>
            `);

            $("#forwardTypeTable").html("");
            for (const [key, value] of Object.entries(data)) {
                $("#forwardTypeTable").append(`<tr>
                    <td>${key}</td>
                    <td>${value}</td>
                </tr>`);
            }

            if (Object.keys(data).length == 0){
                $("#forwardTypeTable").append(`<tr>
                    <td colspan="2"><i class="ui green circle check icon"></i> No Data</td>
                </tr>`);
            }
        });
    }
    getDailySummaryDetails();


    function getDailySummary(){
        $.get("/api/stats/summary?fast=true", function(data){
            $("#summaryTotalCount").text(abbreviateNumber(data.TotalRequest));
            $("#summarySuccCount").text(abbreviateNumber(data.ValidRequest));
            $("#summaryErrCount").text(abbreviateNumber(data.ErrorRequest));
        });
    }
    setInterval(function(){
        getDailySummary();
    }, 10000);
    getDailySummary();

    //Start and stop service button
    function startService(){
        $.post("/api/proxy/enable", {enable: true}, function(data){
            if (data.error != undefined){
                msgbox(data.error, false, 5000);
            }
            initRPStaste();
        });
    }   

    function stopService(){
        $.post("/api/proxy/enable", {enable: false}, function(data){
            if (data.error != undefined){
                msgbox(data.error, false, 5000);
            }
            initRPStaste();
        });
    }


    function handlePortChange(){
        var newPortValue = $("#incomingPort").val();
        if (isNaN(newPortValue - 1) || newPortValue < 1 || newPortValue > 65535){
            msgbox("Invalid incoming port value", false, 5000);
            return;
        }

        $.post("/api/proxy/setIncoming", {incoming: newPortValue}, function(data){
            if (data.error != undefined){
                msgbox(data.error, false, 5000);
            }
            msgbox("Setting Updated");
            initRPStaste();
        });
    }

    function initHTTPtoHTTPSRedirectSetting(){
        $.get("/api/proxy/useHttpsRedirect", function(data){
            if (data == true){
                $("#redirect").checkbox("set checked");
            }

            //Initiate the input listener on the checkbox
            $("#redirect").find("input").on("change", function(){
                let thisValue = $("#redirect").checkbox("is checked");
                    $.ajax({
                        url: "/api/proxy/useHttpsRedirect",
                        data: {set: thisValue},
                        success: function(data){
                            if (data.error != undefined){
                                alert(data.error);
                            }else{
                                //Updated
                                msgbox("Setting Updated");
                                initRPStaste();
                            }
                        }
                    })
            });
        });

          
    }
    initHTTPtoHTTPSRedirectSetting();

    function initTlsSetting(){
        $.get("/api/cert/tls", function(data){
            if (data == true){
                $("#tls").checkbox("set checked");
            }else{
                $("#redirect").addClass('disabled');
            }

            //Initiate the input listener on the checkbox
            $("#tls").find("input").on("change", function(){
                let thisValue = $("#tls").checkbox("is checked");
                if (thisValue){
                    $("#redirect").removeClass('disabled');
                }else{
                    $("#redirect").addClass('disabled');
                }
                $.ajax({
                    url: "/api/cert/tls",
                    data: {set: thisValue},
                    success: function(data){
                        if (data.error != undefined){
                            alert(data.error);
                        }else{
                            //Updated
                            msgbox("Setting Updated");
                            initRPStaste();
                        }
                    }
                })
            });
        })
      
    }
    initTlsSetting();

</script>

<script>
    /*
        Render Network Activity Graph
    */

    /*
        Setup Graph
    */
   

    let rxValues = [];
    let txValues = [];
    let lastRx = 0;
    let lastTx = 0;
    let timestamps = [];
    let netstatRecordTokeep = 60;

    function fetchData() {
        fetch('/api/stats/netstat')
        .then(response => response.json())
        .then(data => {
            let rx = data.RX;
            let tx = data.TX;

            // Calculate change from previous values
            if (lastRx == 0 && lastTx == 0){
                //inital value
                lastRx = rx;
                lastTx = tx;
                return;
            }

            let deltaRx = rx - lastRx;
            let deltaTx = tx - lastTx;

            if (rxValues.length < netstatRecordTokeep){
                //pad init into the array
                for(var i = 0;i<netstatRecordTokeep;i++){
                    rxValues.push(deltaRx);
                    txValues.push(deltaTx);
                    timestamps.push(Date.now() - 1000 * (netstatRecordTokeep - i))
                }
            }

            // Add change to accumulated values
            rxValues.push(deltaRx);
            txValues.push(deltaTx);
            timestamps.push(Date.now());

            // Only keep last netstatRecordTokeep data points
            if (rxValues.length > netstatRecordTokeep) {
                rxValues.shift();
                txValues.shift();
                timestamps.shift();
            }

            lastRx = rx;
            lastTx = tx;

            updateChart();
        })
        .catch(error => {
            //console.error('Failed to fetch data', error);
        });
    }

    function formatBandwidth(bps) {
        const KBPS = 1000;
        const MBPS = 1000 * KBPS;
        const GBPS = 1000 * MBPS;

        if (bps >= GBPS) {
            return (bps / GBPS).toFixed(2) + " Gbps";
        } else if (bps >= MBPS) {
            return (bps / MBPS).toFixed(2) + " Mbps";
        } else if (bps >= KBPS) {
            return (bps / KBPS).toFixed(2) + " Kbps";
        } else {
            return bps.toFixed(2) + " bps";
        }
    }

    var networkStatisticChart;
    function initChart(){
        $.get("/api/stats/netstat", function(data){
        networkStatisticChart = new Chart(
                document.getElementById('networkActivity'),
                {
                    type: 'line',
                    responsive: true,
                    resizeDelay: 100,
                    options: {
                        animation: false,
                        maintainAspectRatio: false,
                        tooltips: {enabled: false},
                        hover: {mode: null},
                        //stepped: 'middle',
                        plugins: {
                            legend: {
                                display: true,
                                position: "right",
                            },
                            title: {
                                display: false,
                                text: 'Network Statistic'
                            },
                        },
                        scales: {
                            x: {
                                display: false,
                                },
                            y: {
                                display: true,
                                scaleLabel: {
                                display: true,
                                labelString: 'Value'
                                },
                                ticks: {
                                    stepSize: 10000000,
                                    callback: function(label, index, labels) {
                                        return formatBandwidth(parseInt(label));
                                    }
                                },
                                gridLines: {
                                    display: true
                                }
                            }
                        }
                    },
                    data: {
                        labels: timestamps,
                        datasets: [
                            {
                                label: 'Inbound',
                                data: rxValues,
                                borderColor: "#4d9dd9",
                                borderWidth: 2,
                                backgroundColor: 'rgba(77, 157, 217, 0.2)',
                                fill: true,
                                pointStyle: false,
                            },
                            {
                                label: 'Outbound',
                                data: txValues,
                                borderColor: '#ffe32b',
                                borderWidth: 2,
                                backgroundColor: 'rgba(255, 227, 43, 0.2)',
                                fill: true,
                                pointStyle: false,
                            }
                        ]
                    }
                }
            );
        });
    }

    function updateChart() {
        //networkStatisticChart.data.datasets[0].data = rxValues;
        //networkStatisticChart.data.datasets[1].data = txValues;
        if (networkStatisticChart != undefined){
            networkStatisticChart.update();
        }
        
    }

    function updateChartSize(){
        let newSize = $("#networkActWrapper").width() - 300;
        if (window.innerWidth > 750){
            newSize = window.innerWidth - $(".toolbar").width() - 500;
        }else{
            newSize = $("#networkActWrapper").width() - 500;
        }
        if (networkStatisticChart != undefined){
            networkStatisticChart.resize(newSize, 200);
        }
    }

    function handleChartAccumulateResize(){
        $("#networkActivity").hide();
        $("#networkActivityPlaceHolder").show();
        if (chartResizeTimeout != undefined){
            clearTimeout(chartResizeTimeout);
        }
        chartResizeTimeout = setTimeout(function(){
            chartResizeTimeout = undefined;
            $("#networkActivityPlaceHolder").hide();
            $("#networkActivity").show();
            updateChartSize();
        }, 300);
    }

    var chartResizeTimeout;
    window.addEventListener('resize', () => {
        handleChartAccumulateResize();
    });

    //Bind event to tab switch
    tabSwitchEventBind["status"] = function(){
        //On switch over to this page, resize the chart
        $("#networkActivityPlaceHolder").hide();
        $("#networkActivity").show().delay(100, function(){
            updateChartSize();
        });
        
    }

    window.addEventListener("focus", function(event){
        handleChartAccumulateResize();
    });

    document.addEventListener("visibilitychange", () => {
        // it could be either hidden or visible
        //handleChartAccumulateResize();
    });



    //Initialize chart data
    initChart();
    fetchData();
    setInterval(fetchData, 1000);
</script>