{{define "title"}}Mirrorlist {{.FileInfo.Path}}{{end}}
{{define "headline"}}{{.FileInfo.Path}}{{end}}

{{define "head"}}
{{if not .LocalJSPath}}
    <!--[if lte IE 8]><script language="javascript" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/excanvas.min.js"></script><![endif]-->
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/jquery.flot.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/jquery.flot.pie.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/flot.tooltip/0.9.0/jquery.flot.tooltip.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.js"></script>
{{else}}
    <!--[if lte IE 8]><script language="javascript" type="text/javascript" src="{{.LocalJSPath}}/flot/0.8.3/excanvas.min.js"></script><![endif]-->
    <script type="text/javascript" src="{{.LocalJSPath}}/jquery/3.3.1/jquery.min.js"></script>
    <script type="text/javascript" src="{{.LocalJSPath}}/flot/0.8.3/jquery.flot.min.js"></script>
    <script type="text/javascript" src="{{.LocalJSPath}}/flot/0.8.3/jquery.flot.pie.min.js"></script>
    <script type="text/javascript" src="{{.LocalJSPath}}/flot.tooltip/0.9.0/jquery.flot.tooltip.min.js"></script>
    <link rel="stylesheet" href="{{.LocalJSPath}}/leaflet/1.3.4/leaflet.css" />
    <script src="{{.LocalJSPath}}/leaflet/1.3.4/leaflet.js"></script>
{{end}}
    <script type="text/javascript">
        $(function() {
            {{$filledchart := false}}
            var mirrordistchartdata = [
                {{range $i, $v := .MirrorList -}}
                    {{if $v.Weight}}{{$filledchart = "yes"}}{ label: '{{$v.Name}}', data: {{$v.Weight}}},{{end}}
                {{- end -}}
                {{if not $filledchart}}{ label: 'Random', data: 100 },{{end}}
            ];
            $.plot('#chart_div', mirrordistchartdata, {
                series: {
                    pie: {
                        show: true,
                        radius: 1,
                        label: {
                            show: true,
                            radius: 0.75,
                            formatter: labelFormatter,
                            threshold: 0.02
                        },
                        combine: {
                            threshold: 0.02 // 0.02 == 2%
                        },
                    }
                },
                legend: {
                    show: true
                },
                grid: {
                    hoverable: true
                },
                tooltip: {
                    show: true,
                    content: "%s: %p.2%",
                    shifts: {
                        x: 10, y: 0
                    },
                    defaultTheme: true
                }
            });
        });
        function labelFormatter(label, series) {
            return "<div style='font-size:8pt; text-align:center; padding:2px; color:white;'>" + series.percent.toFixed(1) + "%</div>";
        }
    </script>
    <style>
    .numberboxinmapblue {
      background:blue; color:white; border:none;
      text-align:center;
      font-size: 11px;
      min-height: 16px; min-width: 16px;
    }
    .numberboxinmapblue:after {
      content: '';
      position: absolute;
      bottom: 0;
      left: 50%;
      width: 0; height: 0;
      border: 4px solid transparent;
      border-top-color: blue;
      border-bottom: 0;
      margin-left: -4px; margin-bottom: -4px;
    }
    .numberboxinmapgreen {
      background:green; color:white; border:none;
      text-align:center;
      font-size: 11px;
      min-height: 16px; min-width: 16px;
    }
    .numberboxinmapgreen:after {
      content: '';
      position: absolute;
      bottom: 0;
      left: 50%;
      width: 0; height: 0;
      border: 4px solid transparent;
      border-top-color: green;
      border-bottom: 0;
      margin-left: -4px; margin-bottom: -4px;
    }
    </style>
{{end}}

{{define "body"}}
    <div style="display: flex; flex-wrap: wrap;">
        <div style="flex-basis: 250px; flex-grow: 1; margin: 8px;">
            <h3>Client</h3>
            <div>You are connecting with IP address <i>{{.IP}}</i>, which belongs to autonomous system <i>{{.ClientInfo.ASName}} (ASN{{.ClientInfo.ASNum}})</i>.<br />
            {{if .ClientInfo.IsValid}}We believe you are {{if .ClientInfo.City}}near <i>{{.ClientInfo.City}}</i> in {{else}}somewhere in {{end}}<i>{{.ClientInfo.Country}}</i> and have selected mirrors based on this.{{else}}We were not able to use your IP to approximate your location, so have chosen the mirrors at random.{{end}}</div>
        </div>

        <div style="flex-basis: 325px; flex-grow: 1; margin: 8px;">
            <h3>File</h3>
            <div>
            {{if not (iszero .FileInfo.ModTime)}}
                The file <b>{{.FileInfo.Path}}</b> has a size of {{sizeof .FileInfo.Size}} ({{.FileInfo.Size}} bytes) and was last modified on {{dateutc .FileInfo.ModTime}}.
            {{else}}
                The file <b>{{.FileInfo.Path}}</b> has not been scanned yet, size and modification time are unknown.
            {{end}}
            </div>
            <div>
                <br/>Known hashes:
                <table class="alt">
                    <tr><td>MD5</td><td style="font-family: monospace; word-break: break-all;">{{if .FileInfo.Md5}}{{.FileInfo.Md5}}{{else}}N/A{{end}}</td></tr>
                    <tr><td>SHA1</td><td style="font-family: monospace; word-break: break-all;">{{if .FileInfo.Sha1}}{{.FileInfo.Sha1}}{{else}}N/A{{end}}</td></tr>
                    <tr><td>SHA256</td><td style="font-family: monospace; word-break: break-all;">{{if .FileInfo.Sha256}}{{.FileInfo.Sha256}}{{else}}N/A{{end}}</td></tr>
                </table>
            </div>
            <br/>
        </div>
    </div>

    <div style="display: flex; flex-wrap: wrap; justify-content: space-around;">
        <div id="map" style="width:600; height:320;"></div>
        <div id="chart_div" style="width:600; height:320;"></div>
    </div>

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

        var mapdata = {
            "mirrors" : [
            {{range $i, $v := .MirrorList}}{{if lt $i 19 }}
            {
                "lat" : {{$v.Latitude}},
                "lon" : {{$v.Longitude}},
                "nr" : {{add $i 1}},
                "color" : {{if $v.Weight}}"green"{{else}}"blue"{{end}}
            },
            {{end}}{{end}}
            ],
            "clientpos" : {
                {{if .ClientInfo.IsValid }}
                "lat" : {{.ClientInfo.Latitude}},
                "lon" : {{.ClientInfo.Longitude}}
                {{else}}
                "lat" : 0.0,
                "lon" : 0.0
                {{end}}
            }
        };
        var latlngbounds = new L.latLngBounds(); // For calculating the boundaries we zoom to on map load
        if ((mapdata.clientpos.lat != 0.0) || (mapdata.clientpos.lon != 0.0)) {
            var nxtmarker = new L.marker([mapdata.clientpos.lat, mapdata.clientpos.lon]);
            nxtmarker.addTo(map);
            latlngbounds.extend([mapdata.clientpos.lat, mapdata.clientpos.lon]);
            if (mapdata.mirrors.length > 0) {
                var polyline = L.polyline( [
                                             [ mapdata.clientpos.lat, mapdata.clientpos.lon ],
                                             [ mapdata.mirrors[0].lat, mapdata.mirrors[0].lon ]
                                           ],
                                           {color: 'blue', opacity: 0.6});
                polyline.addTo(map);
                // No need to update the bounds - that happens when the mirrors dot is added below.
            }
        }
        var showaftercutoff = 3; // How many mirrors without weight to use for calculating bounds
        for (i in mapdata.mirrors) {
            var myIcon = L.divIcon({
                className: 'numberboxinmap' + mapdata.mirrors[i].color,
                html: "" + mapdata.mirrors[i].nr,
                iconSize: null,
                iconAnchor: [8, 20]
            });
            var nxtmarker = new L.marker([mapdata.mirrors[i].lat, mapdata.mirrors[i].lon], {icon: myIcon});
            nxtmarker.addTo(map);
            if (mapdata.mirrors[i].color != "green") {
                showaftercutoff--;
            }
            if (showaftercutoff > 0) {
                latlngbounds.extend([mapdata.mirrors[i].lat, mapdata.mirrors[i].lon]);
            }
        }
        latlngbounds.pad(1);
        map.fitBounds(latlngbounds);
    </script>

    <div>
        <br/>
        <h3>Mirrors</h3>

        {{if .Fallback}}<p style="color:red">Warning: file not served by any mirror, fallbacks to the rescue.</p>{{end}}

    {{if .MirrorList}}
        <table border="0" cellpadding="2" class="alt" style="width: 95%; text-align:left;">
        <thead><tr>
            <th style="width: 3%;">Rank</th><th style="width: 20%;">Mirror Name</th><th style="text-align: right;">URL</th><th style="text-align: center; width: 10%;">Country</th><th style="text-align: center;">Continent</th><th style="text-align: right;">Distance</th><th style="text-align: center;">Selection</th>
        </tr></thead>
        <tbody>
        {{range $i, $v := .MirrorList}}
        <tr{{if not $v.Weight}} style="color: grey;"{{end}}>
            <td style="text-align: right;">{{add $i 1}}.</td><td>{{if $v.SponsorName}}{{$v.SponsorName}}{{else}}{{$v.Name}}{{end}}</td><td style="text-align: right;"><a href="{{concaturl $v.AbsoluteURL $.FileInfo.Path}}">{{$v.AbsoluteURL}}</a></td><td style="text-align: center;">{{$v.CountryCodes}}</td><td style="text-align: center;">{{$v.ContinentCode}}</td><td style="text-align: right;">{{printf "%.0f" $v.Distance}} Km</td><td style="text-align: center;">{{if $v.Weight}}{{if ge $v.Weight 1.0}}{{printf "%.0f" $v.Weight}}{{else}}<1{{end}}%{{else}}n/a{{end}}</td>
        </tr>
        {{end}}
        </tbody>
        </table>
    {{else}}
        <i>No mirrors for this file</i>
    {{end}}

    {{if .ExcludedList}}
        <h3>Excluded Mirrors</h3>
        <table border="0" cellpadding="2" class="alt" style="width: 95%; text-align:left;">
        <thead><tr>
            <th style="width: 23%;">Mirror Name</th><th style="text-align: right;">URL</th><th style="text-align: center; width: 10%;">Country</th><th style="text-align: center;">Continent</th><th style="text-align: right;">Distance</th><th style="text-align: center; width: 20%;">Exclude Reason</th></tr></thead>
        <tbody>
        {{range $i, $v := .ExcludedList}}
            <tr>
                <td>{{if $v.SponsorName}}{{$v.SponsorName}}{{else}}{{$v.Name}}{{end}}<td style="text-align: right;"><a href="{{$v.AbsoluteURL}}">{{$v.AbsoluteURL}}</a></td><td style="text-align: center;">{{$v.CountryCodes}}</td><td style="text-align: center;">{{$v.ContinentCode}}</td><td style="text-align:right;">{{printf "%.0f" $v.Distance}} Km</td><td style="text-align: center;">{{$v.ExcludeReason}}</td>
            </tr>
        {{end}}
        </tbody>
        </table>
        {{end}}
    </div>
{{end}}
