<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Info</title>
    <style>
        
        .medium {width: 300px; height: auto;}
        #map {display: inline-block; width: 500px; height: 500px; border: 1 px solid lightblue;}
        #info {display: inline-block;}
        #attrinfo { 
            display: flex; 
            flex-wrap: wrap;
        }
        #attrinfo div {
            margin: 5px;
        }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.2.0/mapbox-gl.js'></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.2.0/mapbox-gl.css' rel='stylesheet' />
    <link href='loader.css' rel='stylesheet' />
    <script>
    "use strict";

    let map = null;
    
    function init() {
        const urlParams = new URLSearchParams(window.location.search);
        const fullTableName = urlParams.get('table');
        const attrName = urlParams.get("column");
        const attrType = urlParams.get("columntype");
        const geomType = urlParams.get('geomtype');
        const geomColumn = urlParams.get('geom_column');
        document.querySelector('#tablename').innerHTML = `${fullTableName} ${geomColumn}`;
        document.querySelector('#columnname').innerHTML = `${attrName} (${attrType})`;
        document.querySelector('#back').innerHTML = `<a href="tableinfo.html?table=${fullTableName}&geom_column=${geomColumn}">Back to layer info</a>`;

        initMap();
        
        fetch(`data/${fullTableName}/colstats/${attrName}?geom_column=${geomColumn}`).then(response=>{
            const attrInfoElement = document.querySelector('#attrinfo');
            attrInfoElement.innerHTML = "";
            if (!response.ok) {
                try {
                    response.json(json=>attrInfoElement.innerHtml = json.error);
                } catch(err) {
                    attrInfoElement.innerHTML = err;
                }
                return;
            }
            response.json()
            .then(json=>{
                if (json.datatype === 'timestamptz' || json.datatype === 'date') {
                    json.percentiles = json.percentiles.map(percentile=>{
                        percentile.from = percentile.from?new Date(percentile.from):null;
                        percentile.to = percentile.to?new Date(percentile.to):null;
                        return percentile;
                    })
                    json.values = json.values.map(value=>{
                        value.value = value.value?new Date(value.value):null;
                        return value;
                    })
                }
                graphStats(json)
            })
            .catch(err=>
                attrInfoElement.innerHTML = `Failed to parse response, message: ${err.message}`
            );
        })
    }

    function initMap()
    {
        const urlParams = new URLSearchParams(window.location.search);
        const fullTableName = urlParams.get('table');
        const geomType = urlParams.get('geomtype');
        const geomColumn = urlParams.get('geom_column');
        const attrName = urlParams.get("column");
        
        const mapDefinition = {
            container: 'map',
            "style": {
                "version": 8,
                "name": "DefaultBaseStyle",
                "id": "defaultbasestyle",
                "glyphs": `https://free.tilehosting.com/fonts/{fontstack}/{range}.pbf?key=`,
                "sources": {
                    "osmgray": {
                        "type":"raster",
                        "tileSize":256,
                        "tiles":[
                          "https://tiles.edugis.nl/mapproxy/osm/tiles/osmgrayscale_EPSG900913/{z}/{x}/{y}.png?origin=nw"
                        ],
                        "attribution":"&copy; <a href=\"https://www.openstreetmap.org/about\" target=\"copyright\">OpenStreetMap contributors</a>"
                    }
                },
                "layers": [
                    {
                        "id": "osmgray",
                        "type": "raster",
                        "source": "osmgray"
                    }
                ],
                "filter": [
                        "has",
                        `${attrName}`
                    ]
            }
        }
        const bboxll = urlParams.get('bboxll');
        if (bboxll) {
            mapDefinition.bounds = JSON.parse(bboxll);
        }
        map = new mapboxgl.Map(mapDefinition);
        map.on('load', () => {
            let layerType, paint;
            switch (geomType) {
                case 'MULTIPOLYGON':
                case 'POLYGON':
                    layerType = 'fill';
                    paint = {
                        "fill-color": "red",
                        "fill-outline-color": "white",
                        "fill-opacity": 0.8
                    }
                    break;
                case 'MULTILINESTRING':
                case 'LINESTRING':
                    layerType = 'line';
                    paint = {
                        "line-color": "red",
                        "line-width": 1
                    }
                    break;
                case 'MULTIPOINT':
                case 'POINT': 
                    layerType = "circle";
                    paint = {
                        "circle-radius": 5,
                        "circle-color": "red",
                        "circle-stroke-color": "white",
                        "circle-stroke-width" : 1
                    }
                    break;
                default: 
                    break;
            }
            if (!layerType) {
                document.querySelector("#layerjson").innerHTML = `Field geom of type: '${geomType}' not supported<br>Supported types: (MULTI-) POINT/LINE/POLYGON<p>`
            } else {
                const baseUrl = new URL(`/data`, window.location.href).href;
                const layer = {
                    "id": "attrlayer",
                    "type": layerType,
                    "source": {
                        "type": "vector",
                        "tiles": [`${baseUrl}/${fullTableName}/mvt/{z}/{x}/{y}?geom_column=${geomColumn}&columns=${attrName}`],
                    },
                    "source-layer": fullTableName,
                    "paint": paint,
                    "filter": ['has', attrName]
                }
                map.addLayer(layer);
                document.querySelector("#layerjson").innerHTML = `<pre>${JSON.stringify(layer, null, 2)}</pre>`;
            }
        })
        map.on('mousemove', function (e) {
            var features = map.queryRenderedFeatures(e.point).map(function(feature){ return {layer: {id: feature.layer.id, type: feature.layer.type}, properties:(feature.properties)};});
            document.getElementById('info').innerHTML = JSON.stringify(features.map(feature=>feature.properties), null, 2);
        });
    }

    function addCanvas() {
        const container = document.createElement('div');
        container.classList.add('canvascontainer');
        const canvas = document.createElement('canvas');
        container.classList.add('medium');
        container.appendChild(canvas);
        document.querySelector('#attrinfo').appendChild(container);
        return canvas;
    }

    function graphStats(stats) {
        const nullValues = stats.values.filter(value=>value.value === null).reduce((result, value)=>result+value.count,0);
        const rowCount = stats.percentiles.reduce((result, percentile)=>result + percentile.count, 0);
        new Chart(addCanvas(), {
            type: 'doughnut',
            data: {
                labels: ['null','non-null',],
                datasets: [{
                    backgroundColor: ['lightgray', 'red'],
                    borderColor: 'white',
                    borderWidth: 0,
                    data: [nullValues, rowCount]
                }]
                
            }
        });
        if (stats.percentiles.length && typeof(stats.percentiles[0].from) !== 'string') {
            new Chart(addCanvas(), {
                type: 'line',
                data: {
                    labels: stats.percentiles.map((percentile, index, arr)=>Math.round((index/(arr.length - 1)) * 100)),
                    datasets: [{
                        backgroundColor: 'red',
                        borderColor: 'lightred',
                        data: stats.percentiles.map((percentile,index,arr)=>(index===arr.length-1)?percentile.to:percentile.from),
                        fill: false
                    }]
                },
                options : {
                    title: {
                        display: false,
                        text : 'some title'
                    },
                    legend: {
                        display: false
                    },
                    scales: {
                        yAxes: [
                            {
                                scaleLabel: {
                                    display: true,
                                    labelString: stats.column
                                }
                            }
                        ],
                        xAxes: [
                            {
                                scaleLabel: {
                                    display: true,
                                    labelString: 'percentage of rows',
                                    padding: 0
                                }
                            }
                        ]
                    }
                }
            })
        }
        const valuesSummary = stats.values.filter(value=>value.value !== null).slice(0,10);
        const valuesSummeryRowCount = valuesSummary.reduce((result, value)=>result+value.count,0);
        if (rowCount > valuesSummeryRowCount) {
            valuesSummary.push({
                value:"other", 
                count: rowCount - valuesSummeryRowCount
            })
        }
        new Chart(addCanvas(), {
            type: "horizontalBar",
            data: {
                labels: valuesSummary.map(value=>value.value),
                datasets: [
                    {
                        backgroundColor: "red",
                        data: valuesSummary.map(value=>value.count)
                    }
                ]
                
            },
            options : {
                legend: {
                    display: false,
                },
                scales: {
                    xAxes: [
                        {
                            ticks: {
                                min: 0
                            }
                        }
                    ]
                }
            }
        })
    }
    </script>

</head>
<body onload="init()">
    <h1>Attribute information</h1>
    <h2 id="tablename"></h2>
    <h2 id="columnname"></h2>

    <div id="attrinfo">
        <h2>Loading statistics...</h2>
        <div class="loader">
            <div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="dot"></div>
            <div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="dot"></div>
        </div>
    </div>
    <div id="map"></div>
    <div id="info"></div>
    <div id="layerjson"></div>
    <div id="back"></div>
</body>
</html>