{{define "title"}}Mirrorstats{{end}}
{{define "headline"}}Mirrorstats{{end}}

{{define "head"}}
{{if not .LocalJSPath}}
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.4.1/MarkerCluster.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.4.1/leaflet.markercluster.js"></script>
{{else}}
    <link rel="stylesheet" href="{{.LocalJSPath}}/leaflet/1.3.4/leaflet.css" />
    <link rel="stylesheet" href="{{.LocalJSPath}}/leaflet.markercluster/1.4.1/MarkerCluster.css" />
    <script src="{{.LocalJSPath}}/leaflet/1.3.4/leaflet.js"></script>
    <script src="{{.LocalJSPath}}/leaflet.markercluster/1.4.1/leaflet.markercluster.js"></script>
{{end}}
    <style type="text/css">
        #map { }
        .marker-cluster {
            border-radius: 50%;
            opacity: 0.6;
        }
        .marker-good {
            background-color: green;
        }
        .marker-bad {
            background-color: red;
        }
        .marker-mixed {
            background-color: orange;
        }
        .marker-disabled {
            background-color: black;
        }
        .popup-content {
            font-size: 0.8em;
        }
        .tooltip {
            position: relative;
            display: inline-block;
            opacity: 0.8;
        }
        .tooltip .tooltiptext {
            visibility: hidden;
            width: 120px;
            background-color: black;
            color: #fff;
            text-align: center;
            border-radius: 6px;
            padding: 5px 0;
            position: absolute;
            z-index: 1;
            top: -16px;
            left: 110%;
        }
        .tooltip .tooltiptext::after {
            content: "";
            position: absolute;
            top: 50%;
            right: 100%;
            margin-top: -5px;
            border-width: 5px;
            border-style: solid;
            border-color: transparent black transparent transparent;
        }
        .tooltip:hover .tooltiptext {
            visibility: visible;
        }
        .bar-download {
            background-color: #4078C0;
            height: 15px;
        }
        .bar-bytes {
            background-color: #7CA2D3;
            height: 15px;
        }
    </style>
{{end}}

{{define "body"}}
    <div id="map" style="width: 100%; height: 512px;"></div>

    <div id="chart">
        <table class="alt">
            <tr>
                <th>Mirror</th>
                <th>Since 00:00 UTC…</th>
                <th>Last update</th>
                {{if .HasTZAdjustement}}<th>Adjusted TZ</th>{{end}}
            </tr>
            {{range $i, $v := .List}}
            <tr>
                <td rowspan="2">{{$v.Name}}</td>
                <td width="500" class="tooltip"><div class="bar-download" style="width: {{$v.PercentD}}%;"><span class="tooltiptext">{{$v.Downloads}}<br>downloads</span></div></td>
                <td rowspan="2"><span style="color:{{if $v.SyncOffset.Valid}}{{if gt $v.SyncOffset.Value 720}}red{{else if gt $v.SyncOffset.Value 48}}orange{{else}}green{{end}}{{else}}black{{end}}">{{if $v.SyncOffset.Valid}}{{$v.SyncOffset.HumanReadable}}{{else}}unknown{{end}}</span></td>
                {{if $.HasTZAdjustement}}<td rowspan="2">{{if ne $v.TZOffset 0}}{{$v.TZOffset}}{{end}}</td>{{end}}
            </tr>
            <tr>
                <td width="500" class="tooltip"><div class="bar-bytes" style="width: {{$v.PercentB}}%;"><span class="tooltiptext">{{sizeof $v.Bytes}}<br>transferred</span></div></td>
            </tr>
            {{end}}
        </table>
    </div>

    <script>
        var map = L.map('map').setView([20,37], 2);
        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: '&copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
        }).addTo(map);


        var mirrors = {
            "rows" : [
            {{range $i, $v := .MirrorList}}
            {
                "lat" : {{$v.Latitude}},
                "lon" : {{$v.Longitude}},
                "id" : "{{$v.Name}}",
                "enabled": {{$v.Enabled}},
                "URL"    : "{{$v.HttpURL}}",
                "httpUp"  : {{$v.HttpUp}},
                "httpsUp" : {{$v.HttpsUp}},
            },
            {{end}}
            ]
        };

        MirrorMarker = L.Marker.extend({
            options: {
                enabled: false,
                state: '',
                mid: ''
            }
        });

        function generateStatusRow(marker) {
            var color = "red";
            if (marker.options.enabled == false) {
                color = "black";
            } else if (marker.options.state == "up") {
                color = "green";
            } else if (marker.options.state == "degraded") {
                color = "orange";
            }
            return '<tr><td style="background-color: ' + color + '"> &nbsp; </td><td>' + marker.options.mid + '</td></tr>';
        }

        var markers = new L.MarkerClusterGroup({
            showCoverageOnHover: false,
            zoomToBoundsOnClick: false,
            spiderfyOnMaxZoom: false,
            animateAddingMarkers: true,
            iconCreateFunction: function (cluster) {
                var radius = 6;
                var childCount = cluster.getChildCount();
                var area = (Math.PI * (radius * radius)) * childCount;
                var size = Math.sqrt(area / Math.PI) * 2;

                var hasUp = false;
                var hasDown = false;
                var hasDisabled = false;
                for (var i = 0; i < cluster.getAllChildMarkers().length; i++) {
                    if (cluster.getAllChildMarkers()[i].options.enabled == false) {
                        hasDisabled = true;
                        continue
                    }
                    if (cluster.getAllChildMarkers()[i].options.state == "up") {
                        hasUp = true;
                    } else {
                        hasDown = true;
                    }
                }

                var cssClass;
                if (!hasUp && !hasDown && hasDisabled) {
                    cssClass = "marker-disabled";
                } else if (hasUp && !hasDown) {
                    cssClass = "marker-good";
                } else if (!hasUp && hasDown) {
                    cssClass = "marker-bad";
                } else {
                    cssClass = "marker-mixed";
                }

                return new L.divIcon({ html: '<div style="width:'+size+'px;height:'+size+'px;"></div>', className: 'marker-cluster ' + cssClass, iconSize: new L.Point(size, size) });
            }
        });

        var radius = 6;
        var mm = [];
        for (i in mirrors.rows) {
            var area = (Math.PI * (radius * radius));
            var size = Math.sqrt(area / Math.PI) * 2;
            var enabled = mirrors.rows[i].enabled;
            var state = "down";

            if (enabled) {
                if (mirrors.rows[i].httpUp == mirrors.rows[i].httpsUp) {
                    state = mirrors.rows[i].httpUp ? "up" : "down";
                } else if (mirrors.rows[i].URL.startsWith("http://")) {
                    state = mirrors.rows[i].httpUp ? "up" : "down";
                } else if (mirrors.rows[i].URL.startsWith("https://")) {
                    state = mirrors.rows[i].httpsUp ? "up" : "down";
                } else {
                    state = "degraded";
                }
            }

            var cssClass;
            if (!enabled) {
                cssClass = "marker-disabled";
            } else if (state == "up") {
                cssClass = "marker-good";
            } else if (state == "degraded") {
                cssClass = "marker-mixed";
            } else {
                cssClass = "marker-bad";
            }

            var icon = new L.divIcon({ html: '<div style="width:'+size+'px;height:'+size+'px;"></div>', className: 'marker-cluster ' + cssClass, iconSize: new L.Point(size, size) });

            var m = new MirrorMarker([mirrors.rows[i].lat, mirrors.rows[i].lon], {
                icon: icon,
                state: state,
                enabled: enabled,
                mid: mirrors.rows[i].id
            });

            mm.push(m);
        }

        markers.addLayers(mm);

        markers.on('click', function(a) {
            a.layer.bindPopup("<table class='popup-content'>" + generateStatusRow(a.layer) + "</table>").openPopup();
        });

        markers.on('clusterclick', function(a) {
            var content = "";
            for (var i = 0; i < a.layer.getAllChildMarkers().length; i++) {
                content += generateStatusRow(a.layer.getAllChildMarkers()[i]);
            }
            a.layer.bindPopup("<table class='popup-content'>" + content + "</table>").openPopup();
        });

        map.addLayer(markers);
    </script>
{{end}}
