widths = [12, 13, 14, 15, 16, 16, 16, 16];
opas = [0.8, 0.6, 0.5, 0.5, 0.4];
mwidths = [1, 1, 1, 1.5, 2, 3, 5, 6, 6, 4, 3, 2];
function $(id) { return document.getElementById(id); }
function marker(stat, z) {
    if (z > 15) {
        return L.circle(
            [stat.lat, stat.lon],
            {
                color: 'black',
                fillColor: stat.attrerrs ? 'red' : stat.suggestion ? 'blue' : '#78f378', 
                radius: mwidths[23 - z],
                fillOpacity : 1,
                weight : 1,
                id : stat.id
            }
        );
    } else {
        return L.polyline(
            [[stat.lat, stat.lon], [stat.lat, stat.lon]],
            {
                color: stat.attrerrs ? 'red' : stat.suggestion ? 'blue' : '#78f378',
                weight: widths[15 - z],
                opacity: opas[15 - z],
                id : stat.id
            }
        );
    }
}
function poly(group, z) {
    if (group.new) return L.polygon(group.poly, {color: "blue", smoothFactor : 0.4, fillOpacity:0.2})
    return L.polygon(group.poly, {color: '#85f385', smoothFactor : 1, fillOpacity:0.2})
}
function sugArr(sug, z) {
    return [
            L.polyline(sug.arrow, {id : sug.id, color: 'black', smoothFactor : 1, weight: 2, opacity:0.5}),
            L.polyline(sug.arrow, {id : sug.id, color: 'blue', smoothFactor : 1, weight: 1, opacity:0.5})
        ]
    ;
}
function renderStat(stat, ll) {
    var attrrows = {};
    var content = document.createElement('div');
    content.setAttribute("id", "nav")
    var attrTbl = document.createElement('table');
     attrTbl.setAttribute("id", "attr-tbl")
    var suggD = document.createElement('table');
    suggD.setAttribute("id", "sugg")
    if (stat.attrs.name) {        
        content.innerHTML = "Node " + stat.osmid + " (\"" + stat.attrs.name + "\")";
    } else {
        content.innerHTML = "Node " + stat.osmid + "";
    }
    content.appendChild(attrTbl);
    content.appendChild(suggD);
    var tbody = document.createElement('tbody');
    attrTbl.appendChild(tbody);
    for (var key in stat.attrs) {
        var row = document.createElement('tr');
        var col1 = document.createElement('td');
        var col2 = document.createElement('td');
        tbody.appendChild(row);
        row.appendChild(col1);
        row.appendChild(col2);
        col1.innerHTML = "" + key + "";
        for (var i = 0; i <  stat.attrs[key].length; i++) col2.innerHTML += "" + stat.attrs[key][i] + ""+ "
";
        attrrows[key] = row;
    }
    for (var i = 0; i < stat.attrerrs.length; i++) {
        var err = stat.attrerrs[i];
        var row = attrrows[err.attr[0]];
        row.className = "err-" + Math.round(err.conf * 10);
        var info = document.createElement('div');
        if (err.other_osmid != stat.osmid) {
            info.innerHTML = "Does not match node " + err.other_osmid + "";
        } else {
            info.innerHTML = "Does not match '" + err.other_attr[0] + "' = '" + err.other_attr[1];
        }
        info.className = 'attr-err-info';
        row.childNodes[1].appendChild(info);
    }
    if (stat.suggestions.length) {        
        suggD.innerHTML = "Suggestions";
    }
    for (var i = 0; i < stat.suggestions.length; i++) {
        var sugg = stat.suggestions[i];
        var suggDiv = document.createElement('div');
        
        if (sugg.type == 1) {
            suggDiv.innerHTML = "• Move node into a new relation";
        } else if (sugg.type == 2) {
            suggDiv.innerHTML = "• Move node into existing relation " + sugg.target_osm_rel_id + ".";
        } else if (sugg.type == 3) {
            suggDiv.innerHTML = "• Move node from existing relation " + sugg.orig_osm_rel_id + " into new relation (internal id=" + sugg.target_gid + ")";
        } else if (sugg.type == 4) {
            suggDiv.innerHTML = "• Move node from existing relation " + sugg.orig_osm_rel_id + " into existing relation " + sugg.target_osm_rel_id + ".";
        } else if (sugg.type == 5) {
            suggDiv.innerHTML = "• Move node out of existing relation " + sugg.orig_osm_rel_id + "!";
        }
        suggD.appendChild(suggDiv);
    }
    if (map.getZoom() < 18) {
        map.setView(ll, 18, {animate: true});
    }
    L.popup({opacity: 0.8})
        .setLatLng(ll)
        .setContent(content)
        .openOn(map);
}
function openStat(id, ll) {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            var content = JSON.parse(this.responseText);
            renderStat(content, ll);
        }
    };
    xmlhttp.open("GET", "http://localhost:9090/stat?id=" + id, true);
    xmlhttp.send();
}
function groupHl(id) {
    if (!document.groupIdx[id]) return;
    document.groupIdx[id].setStyle({
        'weight': 6,
        'fillOpacity':0.5
});
}
function groupUnHl(id) {
    if (!document.groupIdx[id]) return;
        document.groupIdx[id].setStyle({
        'weight': 3,
        'fillOpacity':0.2
});
}
function nodeHl(id) {
    if (!document.nodeIdx[id]) return;
    document.nodeIdx[id].setStyle({
        'weight': 5,
        'color' : "#eecc00"
});
}
function nodeUnHl(id) {
    if (!document.nodeIdx[id]) return;
        document.nodeIdx[id].setStyle({
        'weight': 1,
        'color' : "black"
});
}
var map = L.map('map', {
  renderer: L.canvas()
}).setView([47.9965, 7.8469], 13);
L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', {
    maxZoom: 23,
    attribution: '© OpenStreetMap, © CARTO',
    id: 'mapbox.streets'
}).addTo(map);
var layer = L.featureGroup().addTo(map);
var labelLayer = L.featureGroup().addTo(map);
map.on("moveend", function () {
    render();
});
function render() {
    var xmlhttp = new XMLHttpRequest();
    if (map.getZoom() < 11) {
        xmlhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                var content = JSON.parse(this.responseText);
                layer.clearLayers();
                labelLayer.clearLayers();
                var blur = 21 - map.getZoom();
                var rad = 21 - map.getZoom();
                blur = Math.max(5, Math.min(9, blur));
                rad = Math.min(10, rad);
                layer.addLayer(L.heatLayer(content.ok, {gradient: {0: '#cbf7cb', 0.5: '#78f378', 1: '#29c329'}, minOpacity: 1, blur: blur, radius: rad, maxZoom: 15}));
                layer.addLayer(L.heatLayer(content.sugg, {gradient: {0: '#7f7fbd', 0.5: '#4444b3', 1: '#0606c1'}, minOpacity: 1, blur: blur-3, radius: rad-3, maxZoom: 15}));
                layer.addLayer(L.heatLayer(content.err, {gradient: {0: '#f39191', 0.5: '#ff5656', 1: '#ff0000'}, minOpacity: 1, blur: blur-3, radius: rad-3, maxZoom: 15}));
            }
        };
        xmlhttp.open("GET", "http://localhost:9090/heatmap?bbox=" + [map.getBounds().getSouthWest().lat, map.getBounds().getSouthWest().lng, map.getBounds().getNorthEast().lat, map.getBounds().getNorthEast().lng].join(","), true);
        xmlhttp.send();
    } else {
        xmlhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                var content = JSON.parse(this.responseText);
                layer.clearLayers();
                labelLayer.clearLayers();
                document.groupIdx = {};                
                document.nodeIdx = {};
                var stations = [];
                var labels = [];
                for (var i = 0; i < content.stats.length; i++) {
                    stat = content.stats[i];
                    var ndMarker = marker(stat, map.getZoom());
                    stations.push(ndMarker);
                    document.nodeIdx[stat.id] = ndMarker;
                }
                var groups = [];
                for (var i = 0; i < content.groups.length; i++) {
                    group = content.groups[i];
                    var groupPoly = poly(group, map.getZoom());
                    groups.push(groupPoly);
                    document.groupIdx[group.id] = groupPoly;
                }
                var suggs = [];
                for (var i = 0; i < content.suggestions.length; i++) {
                    sugg = content.suggestions[i];
                    var a = sugArr(sugg, map.getZoom());
                    suggs.push(a[0]);                    
                    suggs.push(a[1]);
                }
                if (map.getZoom() > 15) {
                   labelLayer.addLayer(L.featureGroup(labels));
                   layer.addLayer(L.featureGroup(groups).on('click', function(a) { console.log(a.layer.options);}));
                   layer.addLayer(L.featureGroup(suggs).on('click', function(a) { openStat(a.layer.options.id, a.layer.getBounds().getCenter());}));
                }
                layer.addLayer(L.featureGroup(stations).on('click', function(a) {
                    openStat(a.layer.options.id, a.layer.getBounds().getCenter());}));
            }
        };
        xmlhttp.open("GET", "http://localhost:9090/map?bbox=" + [map.getBounds().getSouthWest().lat, map.getBounds().getSouthWest().lng, map.getBounds().getNorthEast().lat, map.getBounds().getNorthEast().lng].join(","), true);
        xmlhttp.send();
    }
}
render();