<!-- Leaflet -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css"
        integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA=="
        crossorigin=""/>

<?php
    $currentFile = '';
    foreach ($modelBasesArchivos as $archivo) {
        if($archivo->idTipoArchivo->nombre == 'GeoJSON'){
            $currentFile = $archivo->archivo;
        }
    }
?>

<div class="row">
    <div class="col-md-2">
        <h3>Filtros</h3>
        <h4>Lista de Propiedades</h4>
        <div id="propertyList"></div>
    </div>
    <div class="col-md-10">
        <div id="mapid" style="height: 720px; z-index: 4;"></div>
        <div id="propertiesLegend"></div>
    </div>
</div>

<!-- Leaflet -->
<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"
   integrity="sha512-QVftwZFqvtRNi0ZyCtsznlKSWOStnDORoefr1enyq5mVL4tmKB3S/EnC3rRJcxCPavG10IcrVGSmPh6Qw5lwrg=="
   crossorigin=""></script>
<script src="/RIR/js/palette.js"></script>
<script>
    let geomap = L.map('mapid').setView([21.95774, -101.62595], 5);
    let mapLayer = L.tileLayer('http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png ', {
        attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
    });

    mapLayer.addTo(geomap);

    document.getElementById('geojson').style.display = 'block';
    geomap.invalidateSize(false);
    document.getElementById('geojson').style.display = 'none';

    $('li[class="nav-item"]').click(function(){
        if($(this)[0].id === 'geojson_tab'){
            document.getElementById('geojson').style.display = 'block';
            let fileName = '<?php echo $currentFile;?>';
            if(fileName != ''){
                let target = document.getElementById(fileName);
                loadGeojson(fileName);
            }
        } else{
            document.getElementById('geojson').style.display = 'none';
        }
    })

    $('#meta_tab').click(function(){
        document.getElementById('geojson').style.display = 'none';
    });

    let currentLayer;
    let currentProperties = [];

    function onEachFeature(feature, layer) {
        if (feature.properties) {
            if (!(Object.entries(feature.properties).length === 0 && feature.properties.constructor === Object)){
                let popupContent = '<table class="table table-striped">';
                popupContent += '<thead>';
                popupContent += '<tr>';
                popupContent += '<th>Propiedad</th>';
                popupContent += '<th>Valor</th>';
                popupContent += '</tr>';
                popupContent += '</thead>';
                popupContent += '<tbody>';
                Object.keys(feature.properties).forEach(function (key, index){
                    if(feature.geometry.type == 'Polygon' || feature.geometry.type == 'MultiPolygon'){
                        if(!currentProperties.includes(key)){
                            currentProperties.push(key);
                            let nodeString = '<div class="radio"><label>';
                            nodeString += '<input type="radio" name="geoProperty" id="' + key + '" value="' + key + '" onclick="reloadGeojson()">';
                            nodeString += key;
                            nodeString += '</label></div>';
                            $('#propertyList').append(nodeString);
                        }
                    }
                    popupContent += '<tr>';
                    popupContent += '<td>' + key + '</td>';
                    popupContent += '<td>' + feature.properties[key] + '</td>';
                    popupContent += '</tr>';
                });
                popupContent += '</tbody>';
                popupContent += '</table>';
                layer.bindPopup(popupContent);
            } else {
                let popupContent = '<p>Sin información adicional.</p>';
                layer.bindPopup(popupContent);
            }
        }
    }

    let currentFeatures = []

    function loadGeojson(filename){
        $('#propertiesLegend').hide();
        $.getJSON('/RIR/archivos/' + filename, function(data){
            let geometryType = data.features[0].geometry.type;
            let color = '#000';
            if(geometryType != 'Polygon' && geometryType != 'MultiPolygon'){
                color = '#00b140'
            }
            currentFeatures = data.features;
            currentLayer = L.geoJson(data, {
                style: {
                    fillColor: "#00b140",
                    color: color,
                    fillOpacity: 0.7
                },
                onEachFeature: onEachFeature
            }).addTo(geomap);
            geomap.fitBounds(currentLayer.getBounds());
        });
    }

    let property = '';
    let type = '';
    let frequency = [];
    let colorsProperty = [];
    let stats = {};

    function reloadGeojson(){
        property = $('input[name=geoProperty]:checked').val();
        type = typeof currentFeatures[0].properties[property];
        colorsProperty = [];
        geomap.removeLayer(currentLayer);
        let propertiesData = [];
        for(let i = 0; i < currentFeatures.length; i++){
            propertiesData.push(currentFeatures[i].properties[property]);
        }

        if(type === 'string'){
            frequency = sortByFrequency(propertiesData);
            frequency = frequency.slice(0,5);
            colorByFrequency(frequency);
        }

        if(type === 'number'){
            stats = calculateStatistics(propertiesData);
            colorByQuartile(stats);
        }
    }

    function sortByFrequency(array) {
        var frequency = {};

        array.forEach(function(value) { frequency[value] = 0; });

        var uniques = array.filter(function(value) {
            return ++frequency[value] == 1;
        });

        return uniques.sort(function(a, b) {
            return frequency[b] - frequency[a];
        });
    }

    function colorByFrequency(array){
        let fileName = '<?php echo $currentFile;?>';

        colorsProperty = palette('cb-YlOrRd', array.length + 1);
        colorsProperty = colorsProperty.reverse()

        $.getJSON('/RIR/archivos/' + fileName, function(data){
            currentLayer = L.geoJson(data, {
                style: styleBy,
                onEachFeature: onEachFeature
            }).addTo(geomap);
            geomap.fitBounds(currentLayer.getBounds());
        });

        let legendContainer = document.getElementById('propertiesLegend');
        while(legendContainer.hasChildNodes()){
            legendContainer.removeChild(legendContainer.lastChild);
        }
        for(let i = 0; i < array.length; i++){
            let nodeString = '<p><div style="float: left;width: 25px;height: 25px;background-color:#'+ colorsProperty[i] +'"></div>&nbsp;' + array[i] + '</p>';
            $('#propertiesLegend').append(nodeString);
        }
        let otherNode = '<p><div style="float: left;width: 25px;height: 25px;background-color:#'+ colorsProperty[array.length] +'"></div>&nbsp;Otros</p>';
        $('#propertiesLegend').append(otherNode);
        $('#propertiesLegend').show();
    }

    function styleBy(feature){
        return {
            fillColor: assignColor(feature.properties[property]),
            color: '#000',
            fillOpacity: 0.7
        }
    }

    function colorByQuartile(stats){
        let fileName = '<?php echo $currentFile;?>';

        colorsProperty = palette('cb-YlOrRd', 4);

        $.getJSON('/RIR/archivos/' + fileName, function(data){
            currentLayer = L.geoJson(data, {
                style: styleBy,
                onEachFeature: onEachFeature
            }).addTo(geomap);
            geomap.fitBounds(currentLayer.getBounds());
        });

        let legendContainer = document.getElementById('propertiesLegend');
        while(legendContainer.hasChildNodes()){
            legendContainer.removeChild(legendContainer.lastChild);
        }

        let upper_quartile = '<p><div style="float: left;width: 25px;height: 25px;background-color:#'+ colorsProperty[3] +'"></div>&nbsp;&ge;' + stats.upper_quartile + '</p>';
        $('#propertiesLegend').append(upper_quartile);
        let median = '<p><div style="float: left;width: 25px;height: 25px;background-color:#'+ colorsProperty[2] +'"></div>&nbsp;&ge;' + stats.median + '</p>';
        $('#propertiesLegend').append(median);
        let lower_quartile = '<p><div style="float: left;width: 25px;height: 25px;background-color:#'+ colorsProperty[1] +'"></div>&nbsp;&ge;' + stats.lower_quartile + '</p>';
        $('#propertiesLegend').append(lower_quartile);
        let other = '<p><div style="float: left;width: 25px;height: 25px;background-color:#'+ colorsProperty[0] +'"></div>&nbsp;<' + stats.lower_quartile + '</p>';
        $('#propertiesLegend').append(other);
        $('#propertiesLegend').show();
    }

    function assignColor(propertyValue){
        if(type === 'string'){
            for(let i = 0; i < frequency.length; i++){
                if(propertyValue == frequency[i]){
                    return '#' + colorsProperty[i];
                }
            }
            return '#' + colorsProperty[frequency.length];
        }

        if(type === 'number') {
            if(propertyValue >= stats.upper_quartile) {
                return '#' + colorsProperty[3];
            } else {
                if(propertyValue >= stats.median) {
                    return '#' + colorsProperty[2];
                } else {
                    if(propertyValue >= stats.lower_quartile) {
                        return '#' + colorsProperty[1];
                    } else {
                        if(propertyValue < stats.lower_quartile){
                            return '#' + colorsProperty[0];
                        }
                    }
                }
            }
        }
    }

    function calculateStatistics(data) {
        let stats = {};

        let sum_of_squares = 0;
        let lower_quartile_index_1;
        let lower_quartile_index_2;

        // data needs to be sorted for median etc
        data = data.sort(function(a, b){return a - b});

        // count is just the size of the data set
        stats.count = data.length;

        // initialize total to 0, and then iterate data
        // calculating total and sum of squares
        stats.total = 0;
        for(let i = 0; i < stats.count; i++)
        {
            stats.total += data[i];

            sum_of_squares += Math.pow(data[i], 2);
        }

        // the arithmetic mean is simply the total divided by the count
        stats.arithmetic_mean = stats.total / stats.count;

        // method of calculating median and quartiles is different for odd and even count
        if(is_even(stats.count))
        {
            stats.median = (data[((stats.count) / 2) - 1] + data[stats.count / 2]) / 2;

            // even / even
            if(is_even(stats.count / 2))
            {
                lower_quartile_index_1 = (stats.count / 2) / 2;
                lower_quartile_index_2 = lower_quartile_index_1 - 1;

                stats.lower_quartile = (data[lower_quartile_index_1] + data[lower_quartile_index_2]) / 2;
                stats.upper_quartile = (data[stats.count - 1 - lower_quartile_index_1] + data[stats.count - 1 - lower_quartile_index_2]) / 2;
            }
            // even / odd
            else
            {
                lower_quartile_index_1 = ((stats.count / 2) - 1) / 2;

                stats.lower_quartile = data[lower_quartile_index_1];
                stats.upper_quartile = data[stats.count - 1 - lower_quartile_index_1];
            }
        }
        else
        {
            stats.median = data[((stats.count + 1) / 2) - 1];

            // odd / even
            if(is_even((stats.count - 1) / 2))
            {
                lower_quartile_index_1 = ((stats.count - 1) / 2) / 2;
                lower_quartile_index_2 = lower_quartile_index_1 - 1;

                stats.lower_quartile = (data[lower_quartile_index_1] + data[lower_quartile_index_2]) / 2;
                stats.upper_quartile = (data[stats.count - 1 - lower_quartile_index_1] + data[stats.count - 1 - lower_quartile_index_2]) / 2;
            }
            // odd / odd
            else
            {
                lower_quartile_index_1 = (((stats.count - 1) / 2) - 1) / 2;

                stats.lower_quartile = data[lower_quartile_index_1];
                stats.upper_quartile = data[stats.count - 1 - lower_quartile_index_1];
            }
        }

        // the data is sorted so the mimimum and maximum are the first and last values
        stats.minimum = data[0];
        stats.maximum = data[stats.count - 1];

        // the range is difference between the minimum and the maximum
        stats.range = stats.maximum - stats.minimum;
        // and the inter-quartile range is the difference between the upper and lower quartiles
        stats.inter_quartile_range = stats.upper_quartile - stats.lower_quartile;

        // this is the formula for the POPULATION variance
        stats.variance_population = (sum_of_squares - ((Math.pow(stats.total, 2)) / stats.count)) / stats.count;
        // the standard deviation is the square root of the variance
        stats.standard_deviation_population = Math.sqrt(stats.variance_population);

        // the formula for the sample variance is slightly different in that it use count -1
        stats.variance_sample = (sum_of_squares - ((Math.pow(stats.total, 2)) / stats.count)) / (stats.count - 1);
        // the sample standard deviation is the square root of the sample variance
        stats.standard_deviation_sample = Math.sqrt(stats.variance_sample);

        // this is Pearson's second skewness coefficient, one of many measures of skewness
        stats.skew = (3.0 * (stats.arithmetic_mean - stats.median)) / stats.standard_deviation_population;

        return stats;
    }


    function is_even(n) {
        return n % 2 == 0;
    }
</script>