/*
 * Copyright 2019 - All rights reserved.
 * Rodrigo Tapia-McClung
 *
 * August-September 2019
 */

/* global baseFileSize, formatBytes, Promise, omnivore, JSZip, map, layerControl, updateCharts */
/* exported makeBaseMap, baseLayerPromises, drawnItems */

/* Lines related to displaying loading bar are commented */

let baseLayerPromises = [];
/*    baseSize = 0,
    baseDisplaySize,
    baseLoadedSize = 0,
    baseLoadedDisplaySize,
    baseLayerCounter = 0,
    currentBaseLayer = 1;*/

let drawnItems;
let od, flowMapLayer;

/*Object.keys(baseFileSize).forEach((name) => {
    if (name.split(".")[1] == "zip") {
        baseSize += parseFloat(baseFileSize[name].size); // file size to load for zipped base layers
        baseDisplaySize = formatBytes(baseSize, 2); // size in pretty units
        baseLayerCounter++;
    }
});*/

// function to read compressed json and create a leaflet layer
const zip2Lyr = (zipFile, layerName, layerTemplate) => {
    baseLayerPromises.push(
        new Promise((resolve, reject) => {
            fetch(zipFile) // 1) fetch the url
                .then(response => { // 2) filter on 200 OK
                    if (response.status === 200 || response.status === 0) {
                        return Promise.resolve(response.blob());
                    } else {
                        return Promise.reject(new Error(response.statusText));
                    }
                })
                .then(JSZip.loadAsync) // 3) chain with the zip promise
                .then(zip => {
                    let filename = Object.keys(zip.files)[0];
                    let filetype = filename.split(".").pop();
                    return [zip.file(filename), filetype]; // 4) chain with the text content promise
                })
                .then(([file, type]) => {
                    file.async("string").then(
                        function success(text) { // 5) display the result
                            /*let baseFile = zipFile.split("/")[3];
                            ¬baseLoadedSize += parseFloat(baseFileSize[baseFile].size); // cumulative loaded size
                            baseLoadedDisplaySize = formatBytes(baseLoadedSize); // in pretty units
                            let baseBarWidth = (baseLoadedSize/baseSize*100);*/

                            /*currentBaseLayer++;
                            let baseFiles = currentBaseLayer <= baseLayerCounter ? currentBaseLayer : baseLayerCounter;
                            $("#basemap-fileLoad").html("Cargando capa " + baseFiles + " de " + baseLayerCounter + "<br>" +
                                "<span class=\"progress\"><span id=\"baseBar\" class=\"progress-bar progress-bar-striped progress-bar-animated\" role=\"progressbar\" style=\"width: " + baseBarWidth + "%;\" aria-valuenow=\"" + baseBarWidth + "\" aria-valuemin=\"0\" aria-valuemax=\"100\"></span>" +
                                "<span class=\"justify-content-center d-flex position-absolute w-100\">" + baseLoadedDisplaySize + "/" + baseDisplaySize + "</span></span>");
                            */
                            if (type == "json") {
                                layerTemplate.addData(JSON.parse(text));
                            } else if (type == "topojson") {
                                layerName = omnivore.topojson.parse(text, null, layerTemplate);
                            }
                            resolve("done");
                        },
                        function error(e) {
                            console.log(e);
                            reject("error");
                        }
                    );
                });
        })
    );
}

const createPane = (layerPane, zIndex) => {
    map.createPane(layerPane);
    map.getPane(layerPane).style.zIndex = zIndex;
    map.getPane(layerPane).style["mix-blend-mode"] = "normal";
}

// const getSchoolColor = s => {
//     return s == "Básico" ? "#409400" :
//         s == "Medio superior" ? "#df6400" :
//         "#c0d1e5";
// }

// const getCommerceColor = s => {
//     return s == "Comercio al por menor en supermercados" ? "#9e4244" :
//         s == "Comercio al por menor en tiendas departamentales" ? "#fc464e" :
//         "#c0d1e5";
// }

const getCentrosColor = s => {
    return s == "Primario" ? "#ff5500" :
        s == "Secundario" ? "#8e1973" :
            "#d1ff73";
}

// const getCultivoBorder = s => {
//     return s == "" ? "#e60000" : // :
//         s == "Frijol" ? "#a80084" :
//         "#aaff00"; //;
// }
// const getPoblacionColor = s => {
//     return s > 6000 ? "#6b0601" :
//         s > 4000 ? "#9e4410" :
//         s > 2500 ? "#d68522" :
//         s > 1000 ? "#f7ba3e" :
//         s > 0 ? "#fcdd5d" :
//         "#ffffff";
// }

// const getDensidadColor = s => {
//     return s > 16000 ? "#633096" :
//         s > 11500 ? "#8c6fbd" :
//         s > 7000 ? "#a6a2eb" :
//         s > 2400 ? "#d2d3fa" :
//         s > 0 ? "#f1f0fc" :
//         "#ffffff";
// }

const getHaciaColor = s => {
    return s > 32000 ? "#00451c" :
        s > 6000 ? "#218542" :
            s > 2000 ? "#4bc44f" :
                s > 1000 ? "#b4d787" :
                    "#e3fcd9";
}

const getDesdeColor = s => {
    return s > 6000 ? "#b30000" :
        s > 2000 ? "#fc7f44" :
            s > 1000 ? "#ffaa00" :
                "#ffebbf";
}

const getHaciaPOICColor = s => {
    return s > 4000 ? "#00451c" :
        s > 2000 ? "#218542" :
            s > 1000 ? "#4bc44f" :
                s > 500 ? "#b4d787" :
                    "#e3fcd9";
}

const getDesdePOICColor = s => {
    return s > 1000 ? "#fc7f44" :
        s > 500 ? "#ffaa00" :
            "#ffebbf";
}

const getEntreColor = s => {
    return s > 3500 ? "#a80000" :
        s > 2000 ? "#e64c00" :
            s > 1000 ? "#ffaa00" :
                "#70a800";
}

const getCuencasColor = s => {
    return s == "Bajo Grijalva o Grijalva-Villahermosa" ? "rgba(255,255,190,0.3)" :
        s == "Medio Grijalva o Grijalva-Tuxtla Gutiérrez" ? "rgba(255,170,0,0.3)" :
            "rgba(168,56,0,0.3)";
}

let munis_contexto, lim_zms, zms, conurbaciones, agebs2005, agebs2010, agebs2015, auto2010, auto2014, auto2018, tecnologia2010, tecnologia2014, tecnologia2018, centros, hacia, desde, centrosPOIC, haciaPOIC, desdePOIC;
//supermercados, bancos, agebsbypop, agebsbydens, agricolaoi, agricolapv, escuelas, hospitales, hoteles, subcuencas, tuxtlaVH;

//  *** WMS INEGI ***
// // AEROPUERTOS
// let layer_aeropuertos = new L.tileLayer.wms("http://gaia.inegi.org.mx/NLB/tunnel/wms/wms61?", {
//     layers: "c201",
//     format: "image/svg+xml",
//     transparent: true,
//     //pane: "pane_aeropuertosypistas",
//     attribution: "INEGI 2019",
//     minZoom: 9
// });
// // VIAS FERREAS
// let layer_vferreas = new L.tileLayer.wms("http://gaia.inegi.org.mx/NLB/tunnel/wms/wms61?", {
//     layers: "c202",
//     format: "image/svg+xml",
//     transparent: true,
//     pane: "pane_vferreas",
//     attribution: "INEGI 2019"
// });
//Límite geoestadístico estatal
let layer_limiteEstatal = new L.tileLayer.wms("http://gaia.inegi.org.mx/NLB/tunnel/wms/wms61?", {
    layers: "c100", //Límite geoestadístico estatal
    format: "image/svg+xml",
    transparent: true,
    pane: "pane_estatal",
    attribution: "INEGI 2019"
});
// // NOMBRES DE CUERPOS DE AGUA
// let layer_nombresWB = new L.tileLayer.wms("http://gaia.inegi.org.mx/NLB/tunnel/wms/wms61?", {
//     layers: "t311",
//     format: "image/svg+xml",
//     transparent: true,
//     attribution: "INEGI 2019",
//     minZoom: 9,
//     pane: "pane_wbnames"
// });
//RED NACIONAL DE CAMINOS
let layer_RedNacionalCaminos = new L.tileLayer.wms("http://gaia.inegi.org.mx/NLB/tunnel/wms/wms61?", {
    layers: "RNC", //Red nacional de caminos
    format: "image/svg+xml",
    transparent: true,
    pane: "pane_carreteras",
    attribution: "INEGI 2019"
});
//MANZANAS
// let layer_manzanaswms = new L.tileLayer.wms("http://gaia.inegi.org.mx/NLB/tunnel/wms/wms61?", {
//     layers: "c104",
//     format: "image/svg+xml",
//     transparent: true,
//     pane: "pane_manzanas",
//     attribution: "INEGI 2019",
//     minZoom: 13,
//     maxZoom: 18
// });
//LOCALIDAD URBANA
let layer_locUrban = new L.tileLayer.wms("http://gaia.inegi.org.mx/NLB/tunnel/wms/wms61?", {
    layers: "c102",
    format: "image/svg+xml",
    transparent: true,
    pane: "pane_locs",
    attribution: "INEGI 2019"
});
//Límite geoestadístico municipal
let layer_limiteMunicipal = new L.tileLayer.wms("http://gaia.inegi.org.mx/NLB/tunnel/wms/wms61?", {
    layers: "c101", //Límite geoestadístico municipal
    format: "image/svg+xml",
    transparent: true,
    pane: "pane_munis",
    attribution: "INEGI 2019",
    minZoom: 9
});

//  *** FIN WMS INEGI ***
let layer_auto2010 = new L.geoJson(null, {
    attribution: "",
    pane: "pane_auto2010",
    // minZoom: 9,
    //onEachFeature: pop_escuelas,
    pointToLayer: function(feature, latlng) {
        // let context = {
        //     feature: feature,
        //     variables: {}
        // };
        let autoMarker = L.BeautifyIcon.icon({
            icon: "desechos",
            iconSize: [0, 0],
            iconAnchor: [7, 10],
            iconShape: "", //"circle",
            popupAnchor: [0, 0],
            innerIconStyle: "font-size: 15px;",
            html: "<span class=\"fa-stack\"><i class=\"fas fa-desechos fa-stack-1x\" style=\"color:rgba(0,121,159,0.3);font-size: 8px;\"></i></span>",
            borderWidth: 0,
            borderColor: "transparent",
            backgroundColor: "transparent" //,
            // textColor: "#C0C0C0"
        });
        return new L.Marker(latlng, {
            icon: autoMarker
        });
    }
});

let layer_auto2014 = new L.geoJson(null, {
    attribution: "",
    pane: "pane_auto2014",
    // minZoom: 9,
    //onEachFeature: pop_escuelas,
    pointToLayer: function(feature, latlng) {
        // let context = {
        //     feature: feature,
        //     variables: {}
        // };
        let autoMarker = L.BeautifyIcon.icon({
            icon: "desechos",
            iconSize: [0, 0],
            iconAnchor: [7, 10],
            iconShape: "", //"circle",
            popupAnchor: [0, 0],
            innerIconStyle: "font-size: 15px;",
            html: "<span class=\"fa-stack\"><i class=\"fas fa-desechos fa-stack-1x\" style=\"color:rgba(60,75,175,0.3);font-size: 8px;\"></i></span>",
            borderWidth: 0,
            borderColor: "transparent",
            backgroundColor: "transparent" //,
            // textColor: "#C0C0C0"
        });
        return new L.Marker(latlng, {
            icon: autoMarker
        });
    }
});

let layer_auto2018 = new L.geoJson(null, {
    attribution: "",
    pane: "pane_auto2018",
    // minZoom: 9,
    //onEachFeature: pop_escuelas,
    pointToLayer: function(feature, latlng) {
        // let context = {
        //     feature: feature,
        //     variables: {}
        // };
        let autoMarker = L.BeautifyIcon.icon({
            icon: "desechos",
            iconSize: [0, 0],
            iconAnchor: [7, 10],
            iconShape: "", //"circle",
            popupAnchor: [0, 0],
            innerIconStyle: "font-size: 15px;",
            html: "<span class=\"fa-stack\"><i class=\"fas fa-desechos fa-stack-1x\" style=\"color:rgba(35,53,249,0.3);font-size: 8px;\"></i></span>",
            borderWidth: 0,
            borderColor: "transparent",
            backgroundColor: "transparent" //,
            // textColor: "#C0C0C0"
        });
        return new L.Marker(latlng, {
            icon: autoMarker
        });
    }
});

let layer_tecnologia2010 = new L.geoJson(null, {
    attribution: "",
    pane: "pane_tecnologia2010",
    // minZoom: 9,
    //onEachFeature: pop_escuelas,
    pointToLayer: function(feature, latlng) {
        // let context = {
        //     feature: feature,
        //     variables: {}
        // };
        let autoMarker = L.BeautifyIcon.icon({
            icon: "desechos",
            iconSize: [0, 0],
            iconAnchor: [7, 10],
            iconShape: "", //"circle",
            popupAnchor: [0, 0],
            innerIconStyle: "font-size: 12px;",
            html: "<span class=\"fa-stack\"><i class=\"fas fa-desechos fa-stack-1x\" style=\"color:rgba(88,24,69,0.3);font-size: 8px;\"></i></span>",
            borderWidth: 0,
            borderColor: "transparent",
            backgroundColor: "transparent" //,
            // textColor: "#C0C0C0"
        });
        return new L.Marker(latlng, {
            icon: autoMarker
        });
    }
});

let layer_tecnologia2014 = new L.geoJson(null, {
    attribution: "",
    pane: "pane_tecnologia2014",
    // minZoom: 9,
    //onEachFeature: pop_escuelas,
    pointToLayer: function(feature, latlng) {
        // let context = {
        //     feature: feature,
        //     variables: {}
        // };
        let autoMarker = L.BeautifyIcon.icon({
            icon: "desechos",
            iconSize: [0, 0],
            iconAnchor: [7, 10],
            iconShape: "", //"circle",
            popupAnchor: [0, 0],
            innerIconStyle: "font-size: 8px;",
            html: "<span class=\"fa-stack\"><i class=\"fas fa-desechos fa-stack-1x\" style=\"color:rgba(144,12,63,0.3);font-size: 8px;\"></i></span>",
            borderWidth: 0,
            borderColor: "transparent",
            backgroundColor: "transparent" //,
            // textColor: "#C0C0C0"
        });
        return new L.Marker(latlng, {
            icon: autoMarker
        });
    }
});

let layer_tecnologia2018 = new L.geoJson(null, {
    attribution: "",
    pane: "pane_tecnologia2018",
    // minZoom: 9,
    //onEachFeature: pop_escuelas,
    pointToLayer: function(feature, latlng) {
        // let context = {
        //     feature: feature,
        //     variables: {}
        // };
        let autoMarker = L.BeautifyIcon.icon({
            icon: "desechos",
            iconSize: [0, 0],
            iconAnchor: [7, 10],
            iconShape: "", //"circle",
            popupAnchor: [0, 0],
            innerIconStyle: "font-size: 8px;",
            html: "<span class=\"fa-stack\"><i class=\"fas fa-desechos fa-stack-1x\" style=\"color:rgba(199,0,57,0.3);font-size: 8px;\"></i></span>",
            borderWidth: 0,
            borderColor: "transparent",
            backgroundColor: "transparent" //,
            // textColor: "#C0C0C0"
        });
        return new L.Marker(latlng, {
            icon: autoMarker
        });
    }
});
// let aeropuertosypistasaereas = new L.layerGroup([layer_aeropuertos, layer_pistasaereas], {
//     pane: "pane_aeropuertosypistas",
//     minZoom: 9
// });



// let layer_supermercados = new L.geoJson(null, {
//     attribution: "",
//     pane: "pane_supermercados",
//     //onEachFeature: pop_escuelas,
//     pointToLayer: function(feature, latlng) {
//         // let context = {
//         //     feature: feature,
//         //     variables: {}
//         // };
//         let shoppingMarker = L.BeautifyIcon.icon({
//             icon: "shopping-cart",
//             iconSize: [0, 0],
//             iconAnchor: [7, 10],
//             iconShape: "circle",
//             popupAnchor: [0, 0],
//             innerIconStyle: "font-size: 15px;",
//             // html: "<span class=\"fa-stack\"><i class=\"fas fa-shopping-cart fa-stack-1x\" style=\"color:#808080;\"></i></span>",
//             borderWidth: 0,
//             borderColor: "transparent",
//             backgroundColor: "transparent",
//             textColor: getCommerceColor(feature.properties["nombre_act"]) //textColor: "#C0C0C0"
//         });
//         return new L.Marker(latlng, {
//             icon: shoppingMarker
//         });
//     }
// });

// let layer_bancos = new L.geoJson(null, {
//     attribution: "",
//     pane: "pane_bancos",
//     //onEachFeature: pop_escuelas,
//     pointToLayer: function(feature, latlng) {
//         // let context = {
//         //     feature: feature,
//         //     variables: {}
//         // };
//         let bancosMarker = L.BeautifyIcon.icon({
//             icon: "desechos",
//             iconSize: [0, 0],
//             iconAnchor: [7, 10],
//             iconShape: "", //"circle",
//             popupAnchor: [0, 0],
//             innerIconStyle: "font-size: 12px;",
//             html: "<span class=\"fa-stack\"><i class=\"fas fa-desechos fa-stack-1x\" style=\"color:#c0ca33;\"></i><i class =\"fas fa-dollar fa-stack-1x fa-inverse\"></i></span>",
//             borderWidth: 0,
//             borderColor: "transparent",
//             backgroundColor: "transparent",
//             textColor: "#C0C0C0"
//         });
//         return new L.Marker(latlng, {
//             icon: bancosMarker
//         });
//     }
// });

// let layer_escuelas = new L.geoJson(null, {
//     attribution: "",
//     pane: "pane_escuelas",
//     //onEachFeature: pop_escuelas,
//     pointToLayer: function(feature, latlng) {
//         // let context = {
//         //     feature: feature,
//         //     variables: {}
//         // };
//         let escuelaMarker = L.BeautifyIcon.icon({
//             icon: "escuela",
//             iconSize: [0, 0],
//             iconAnchor: [7, 10],
//             iconShape: "circle",
//             popupAnchor: [0, 0],
//             innerIconStyle: "font-size: 15px;",
//             borderWidth: 0,
//             borderColor: "transparent",
//             backgroundColor: "transparent",
//             textColor: getSchoolColor(feature.properties["Nivel"])
//         });
//         return new L.Marker(latlng, {
//             icon: escuelaMarker
//         });
//     }
// });

// let layer_hospitales = new L.geoJson(null, {
//     attribution: "",
//     pane: "pane_hospitales",
//     //onEachFeature: pop_hospitales,
//     pointToLayer: function(feature, latlng) {
//         // let context = {
//         //     feature: feature,
//         //     variables: {}
//         // };
//         let hospitalMarker = L.BeautifyIcon.icon({
//             icon: "desechos",
//             iconSize: [0, 0],
//             iconAnchor: [7, 10],
//             iconShape: "circle",
//             popupAnchor: [0, 0],
//             innerIconStyle: "font-size: 13px;",
//             html: "<span class=\"fa-stack\"><i class=\"fas fa-desechos fa-stack-1x\" style=\"color:#ff0000;\"></i><i class =\"fas fa-plus-circle fa-stack-1x fa-inverse\"></i></span>",
//             borderWidth: 0,
//             borderColor: "transparent",
//             backgroundColor: "transparent",
//             textColor: "#C0C0C0"
//         });
//         return new L.Marker(latlng, {
//             icon: hospitalMarker
//         });
//     }
// });

// let layer_hoteles = new L.geoJson(null, {
//     attribution: "",
//     pane: "pane_hoteles",
//     //onEachFeature: pop_hoteles,
//     pointToLayer: function(feature, latlng) {
//         // let context = {
//         //     feature: feature,
//         //     variables: {}
//         // };
//         let hotelMarker = L.BeautifyIcon.icon({
//             icon: "bed",
//             iconSize: [0, 0],
//             iconAnchor: [7, 10],
//             iconShape: "circle",
//             popupAnchor: [0, 0],
//             innerIconStyle: "font-size: 12px;",
//             borderWidth: 0,
//             borderColor: "transparent",
//             backgroundColor: "transparent",
//             textColor: "#808080"
//         });
//         return new L.Marker(latlng, {
//             icon: hotelMarker
//         });
//     }
// });

const style_munis_contexto = () => {
    return {
        pane: "pane_munis_contexto",
        opacity: 1,
        color: "rgba(110,110,110,0.4)",
        //dashArray: "3 2",
        lineCap: "butt",
        lineJoin: "miter",
        weight: 1.0,
        fill: true,
        fillOpacity: 1,
        fillColor: "rgba(255,255,212,0.4)"
    }
}
let layer_munis_contexto = new L.geoJson(null, {
    attribution: "",
    pane: "pane_munis_contexto",
    //onEachFeature: pop_cuencas,
    style: style_munis_contexto
});

const style_limZMs = () => {
    return {
        pane: "pane_limZMs",
        opacity: 1,
        color: "rgba(168,0,0,1)",
        dashArray: "",
        lineCap: "butt",
        lineJoin: "miter",
        weight: 1.0,
        fillOpacity: 0
    }
}

let layer_limZMs = new L.geoJson(null, {
    attribution: "",
    pane: "pane_limZMs",
    //onEachFeature: pop_limZMs,
    style: style_limZMs
});

const style_ZMs = () => {
    return {
        pane: "pane_ZMs",
        opacity: 1,
        color: "rgba(110,110,100,1)",
        dashArray: "",
        lineCap: "butt",
        lineJoin: "miter",
        weight: 1.0,
        fillOpacity: 1,
        fillColor: "rgba(255,170,0,1)"
    }
}

let layer_ZMs = new L.geoJson(null, {
    attribution: "",
    pane: "pane_ZMs",
    //onEachFeature: pop_ZMs,
    style: style_ZMs
});

const style_conurbaciones_rurbana = () => {
    return {
        pane: "pane_conurbaciones",
        opacity: 1,
        color: "rgba(35,35,35,0.1)",
        dashArray: "",
        lineCap: "butt",
        lineJoin: "miter",
        weight: 1.0,
        fillOpacity: 1,
        fillColor: "rgba(255,0,0,0.1)"
    }
}

let layer_conurbaciones_rurbana = new L.geoJson(null, {
    attribution: "",
    pane: "pane_conurbaciones",
    //onEachFeature: pop_ZMs,
    style: style_conurbaciones_rurbana
});

const style_agebs2005 = () => {
    return {
        // pane: "pane_agebs2005",
        opacity: .9,
        color: "#d6c996",
        //dashArray: "3 2",
        lineCap: "butt",
        lineJoin: "miter",
        weight: 0.5, //1.0,
        fill: true,
        fillOpacity: 0.9, //1,
        fillColor: "#ffffb3"
    }
}

let layer_agebs2005 = new L.geoJson(null, {
    attribution: "",
    // pane: "pane_agebs2005",
    //onEachFeature: pop_ANPs,
    style: style_agebs2005,
    interactive: false
});

const style_agebs2010 = () => {
    return {
        // pane: "pane_agebs2010",
        opacity: 1,
        color: "#ffaa00",
        //dashArray: "3 2",
        lineCap: "butt",
        lineJoin: "miter",
        weight: 0.5, //1.0,
        fill: true,
        fillOpacity: 1,
        fillColor: "#ffaa00"
    }
}

let layer_agebs2010 = new L.geoJson(null, {
    attribution: "",
    // pane: "pane_agebs2010",
    //onEachFeature: pop_ANPs,
    style: style_agebs2010,
    interactive: false
});

const style_agebs2015 = () => {
    return {
        // pane: "pane_agebs2015",
        opacity: 1,
        color: "#730000",
        //dashArray: "3 2",
        lineCap: "butt",
        lineJoin: "miter",
        weight: 1.0,
        fill: true,
        fillOpacity: 1,
        fillColor: "#730000"
    }
}

let layer_agebs2015 = new L.geoJson(null, {
    attribution: "",
    // pane: "pane_agebs2015",
    //onEachFeature: pop_ANPs,
    style: style_agebs2015,
    interactive: false
});

let crecimiento_urbano = new L.layerGroup([layer_agebs2005, layer_agebs2010, layer_agebs2015], {
    pane: "pane_agebs",
    // minZoom: 9
});

const style_centros = feature => {
    return {
        pane: "pane_centros",
        opacity: 1,
        color: "rgba(110,100,110,0.7)",
        //dashArray: "3 2",
        lineCap: "butt",
        lineJoin: "miter",
        weight: 0.5, //1.0,
        fill: true,
        fillOpacity: .4,
        fillColor: getCentrosColor(feature.properties["OCUPADOS"]),
        fillPattern: "stripes"
    }
}

let layer_centros = new L.geoJson(null, {
    attribution: "",
    pane: "pane_centros",
    //onEachFeature: pop_ANPs,
    style: style_centros,
    interactive: false
});

const style_hacia = feature => {
    return {
        pane: "pane_hacia",
        opacity: 1,
        color: "rgba(110,110,110,0.7)",
        //dashArray: "3 2",
        lineCap: "butt",
        lineJoin: "miter",
        weight: 0.5, //1.0,
        fill: true,
        fillOpacity: 0.5,
        fillColor: getHaciaColor(feature.properties["PERSONAS"])
    }
}

let layer_hacia = new L.geoJson(null, {
    attribution: "",
    pane: "pane_hacia",
    //onEachFeature: pop_ANPs,
    style: style_hacia
});

const style_desde = feature => {
    return {
        pane: "pane_desde",
        opacity: 1,
        color: "rgba(110,110,110,0.7)",
        //dashArray: "3 2",
        lineCap: "butt",
        lineJoin: "miter",
        weight: 0.5, //1.0,
        fill: true,
        fillOpacity: 0.5,
        fillColor: getDesdeColor(feature.properties["PERSONAS"])
    }
}

let layer_desde = new L.geoJson(null, {
    attribution: "",
    pane: "pane_desde",
    //onEachFeature: pop_ANPs,
    style: style_desde
});

const style_centrosPOIC = feature => {
    return {
        pane: "pane_centrosPOIC",
        opacity: 1,
        color: "rgba(110,100,110,0.7)",
        //dashArray: "3 2",
        lineCap: "butt",
        lineJoin: "miter",
        weight: 0.5, //1.0,
        fill: true,
        fillOpacity: .4,
        fillColor: getCentrosColor(feature.properties["POIC"]),
        //fillPattern: "stripes"
    }
}

let layer_centrosPOIC = new L.geoJson(null, {
    attribution: "",
    pane: "pane_centrosPOIC",
    //onEachFeature: pop_ANPs,
    style: style_centrosPOIC
});

const style_haciaPOIC = feature => {
    return {
        pane: "pane_haciaPOIC",
        opacity: 1,
        color: "rgba(110,110,110,0.7)",
        //dashArray: "3 2",
        lineCap: "butt",
        lineJoin: "miter",
        weight: 0.5, //1.0,
        fill: true,
        fillOpacity: 0.5,
        fillColor: getHaciaPOICColor(feature.properties["PERSONAS"])
    }
}

let layer_haciaPOIC = new L.geoJson(null, {
    attribution: "",
    pane: "pane_haciaPOIC",
    //onEachFeature: pop_ANPs,
    style: style_haciaPOIC
});

const style_desdePOIC = feature => {
    return {
        pane: "pane_desdePOIC",
        opacity: 1,
        color: "rgba(110,110,110,0.7)",
        //dashArray: "3 2",
        lineCap: "butt",
        lineJoin: "miter",
        weight: 0.5, //1.0,
        fill: true,
        fillOpacity: 0.5,
        fillColor: getDesdePOICColor(feature.properties["PERSONAS"])
    }
}

let layer_desdePOIC = new L.geoJson(null, {
    attribution: "",
    pane: "pane_desdePOIC",
    //onEachFeature: pop_ANPs,
    style: style_desdePOIC
});

/*const styleDrawnItems = () => {
    let currentId = 0;
    drawnItems.eachLayer(l => {
        l.feature.properties.id = currentId;
        l.feature.properties.color = d3.schemeCategory10[currentId];

        l.setStyle({
            fillColor: d3.schemeCategory10[currentId],
            opacity: 0.5,
            fillOpacity: 0.2,
            color: d3.schemeCategory10[currentId],
            weight: 4
        });
        currentId++;
    });
}

const toggleButtons = () => {
    let buttons = [];
    buttons.push(document.getElementsByClassName("leaflet-draw-draw-polyline")[0]);
    buttons.push(document.getElementsByClassName("leaflet-draw-draw-polygon")[0]);
    buttons.push(document.getElementsByClassName("leaflet-draw-draw-rectangle")[0]);

    buttons.forEach(b => {
        // disable buttons if there are 10 drawn items
        if (drawnItems.getLayers().length >= 10) {
            b.onClick = "preventEventDefault(); return false";
            b.classList.add("draw-control-disabled");
            // enable buttons if there are less than 10 drawn items
        } else if (drawnItems.getLayers().length < 10) {
            b.onClick = null;
            b.classList.remove("draw-control-disabled");
        }
    })
}*/

const makeBaseMap = () => {
    createPane("pane_munis", 402);
    createPane("pane_munis_contexto", 402);
    createPane("pane_ZMs", 403);
    createPane("pane_limZMs", 404);
    createPane("pane_conurbaciones", 404);
    createPane("pane_locs", 405);
    createPane("pane_cuencas", 406);
    createPane("pane_buffer", 407);
    createPane("pane_manzanas", 408);
    createPane("pane_estatal", 409);
    createPane("pane_carreteras", 410);
    // createPane("pane_wbnames", 421);
    createPane("pane_auto2010", 411);
    createPane("pane_auto2014", 411);
    createPane("pane_auto2018", 411);
    createPane("pane_tecnologia2010", 412);
    createPane("pane_tecnologia2014", 412);
    createPane("pane_tecnologia2018", 412);
    createPane("pane_centros", 420);
    createPane("pane_desde", 414);
    createPane("pane_hacia", 415);
    createPane("pane_centrosPOIC", 420);
    createPane("pane_desdePOIC", 414);
    createPane("pane_haciaPOIC", 415);
    createPane("pane_agebs", 421);
    createPane("pane_flujos", 422);

    /*$("#basemap-fileLoad").html("Cargando capa 1 de " + baseLayerCounter + "<br>" +
        "<span class=\"progress\"><span id=\"baseBar\" class=\"progress-bar progress-bar-striped progress-bar-animated\" role=\"progressbar\" style=\"width: 0%;\" aria-valuenow=\"0\" aria-valuemin=\"0\" aria-valuemax=\"100\"></span>" +
        "<span class=\"justify-content-center d-flex position-absolute w-100\">0/" + baseDisplaySize + "</span></span>");*/

    zip2Lyr("../centropais/data/munis_contexto.zip", munis_contexto, layer_munis_contexto);
    layerControl.addOverlay(layer_munis_contexto, "&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"rgba(255,255,212,0.4)\" stroke=\"rgba(110,100,100,0.4)\" stroke-dasharray=\" \"></rect></svg>&nbsp; Municipios para dar contexto a la región");
    zip2Lyr("../centropais/data/munis_conurbaciones_rurbana.zip", conurbaciones, layer_conurbaciones_rurbana);
    layerControl.addOverlay(layer_conurbaciones_rurbana, "&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"rgba(255,0,0,0.1)\" stroke=\"rgba(35,35,35,0.4)\" stroke-dasharray=\" \"></rect></svg>&nbsp; Municipios que albergan las conurbaciones de la región");
    layerControl.addOverlay(layer_RedNacionalCaminos, "Red Nacional de Caminos <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src=\"http://gaia.inegi.org.mx/NLB/tunnel/wms/mdm6wms?map=/opt/map/mdm60/mdm61leyendaprueba.map&Request=GetLegendGraphic&format=image/png&Version=1.1.1&Service=WMS&LAYER=c200\" alt=\"Red Nacional de Caminos\"/>");
    zip2Lyr("../centropais/data/agebs_urbanos2005.zip", agebs2005, layer_agebs2005);
    zip2Lyr("../centropais/data/expansion_agebs2010.zip", agebs2010, layer_agebs2010);
    zip2Lyr("../centropais/data/expansion_agebs2015.zip", agebs2015, layer_agebs2015);
    layerControl.addOverlay(crecimiento_urbano, "Crecimiento urbano 2005-2015<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#730000\"   stroke=\"#730000\" stroke-dasharray=\" \"></rect></svg> Expansión del área de los AGEB's urbanos 2015<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#ffaa00\" stroke = \"#ffaa00\" stroke-dasharray=\" \"></rect></svg> Expansión del área de los AGEB's urbanos 2010<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#ffffd3\" stroke = \"#d6c996\" stroke-dasharray=\" \"></rect></svg> Área ocupada por los AGEBS's urbanos en 2005");
    crecimiento_urbano.addTo(map);
    zip2Lyr("../centropais/data/industria_automotriz_2010.zip", auto2010, layer_auto2010);
    layerControl.addOverlay(layer_auto2010, "&nbsp; <i class=\"fa fa-desechos\" style=\"color:#00799f;margin-top:3px;margin-left:0px;font-size: 8px;opacity:0.75;\"></i>&nbsp;&nbsp;Unidades económicas en la industria automotriz 2010 ");
    zip2Lyr("../centropais/data/industria_automotriz_2014.zip", auto2014, layer_auto2014);
    layerControl.addOverlay(layer_auto2014, "&nbsp; <i class=\"fa fa-desechos\" style=\"color:#3c4baf;margin-top:3px;margin-left:0px;font-size: 8px;opacity:0.75;\"></i>&nbsp;&nbsp;Unidades económicas en la industria automotriz 2014 ");
    zip2Lyr("../centropais/data/industria_automotriz_2018.zip", auto2018, layer_auto2018);
    layerControl.addOverlay(layer_auto2018, "&nbsp; <i class=\"fa fa-desechos\" style=\"color:#2335f9;margin-top:3px;margin-left:0px;font-size: 8px;opacity:0.75;\"></i>&nbsp;&nbsp;Unidades económicas en la industria automotriz 2018 ");
    zip2Lyr("../centropais/data/tecnologia_media_alta_2010.zip", tecnologia2010, layer_tecnologia2010);
    layerControl.addOverlay(layer_tecnologia2010, "&nbsp; <i class=\"fa fa-desechos\" style=\"color:#581845;margin-top:3px;margin-left:0px;font-size: 8px;opacity:0.75;\"></i>&nbsp;&nbsp;Unidades económicas en la industria de tecnología media-alta 2010 ");
    zip2Lyr("../centropais/data/tecnologia_media_alta_2014.zip", tecnologia2014, layer_tecnologia2014);
    layerControl.addOverlay(layer_tecnologia2014, "&nbsp; <i class=\"fa fa-desechos\" style=\"color:#900c3f;margin-top:3px;margin-left:0px;font-size: 8px;opacity:0.75;\"></i>&nbsp;&nbsp;Unidades económicas en la industria de tecnología media-alta 2014 ");
    zip2Lyr("../centropais/data/tecnologia_media_alta_2018.zip", tecnologia2018, layer_tecnologia2018);
    layerControl.addOverlay(layer_tecnologia2018, "&nbsp; <i class=\"fa fa-desechos\" style=\"color:#c70039;margin-top:3px;margin-left:0px;font-size: 8px;opacity:0.75;\"></i>&nbsp;&nbsp;Unidades económicas en la industria de tecnología media-alta 2018 ");
    zip2Lyr("../centropais/data/Centros_de_mercado_de_ocupados.zip", centros, layer_centros);
    layerControl.addOverlay(layer_centros, "Centros de mercado <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#d1ff73\"   stroke=\"#aaff00\" stroke-dasharray=\" \"></rect></svg> Terciario<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#8e1973\" stroke = \"#a80084\" stroke-dasharray=\" \"></rect></svg> Secundario<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#ff5500\" stroke = \"#e60000\" stroke-dasharray=\" \"></rect></svg> Primario");
    layer_centros.addTo(map);
    zip2Lyr("../centropais/data/hacia.zip", hacia, layer_hacia);
    layerControl.addOverlay(layer_hacia, "Número de ocupados <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#e3fcd9\"   stroke=\"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> 0 - 1000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#b4d787\" stroke = \"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> 1001 - 2000<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#4bc44f\" stroke = \"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> 2001 - 6000 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#218542\" stroke = \"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> 6001 - 32000 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#00451c\" stroke = \"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> 32001 - 53300");
    zip2Lyr("../centropais/data/desde.zip", desde, layer_desde);
    layerControl.addOverlay(layer_desde, "Número de ocupados <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#ffebbf\"   stroke=\"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> Menos de 1000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#ffaa00\" stroke = \"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> 1001 - 2000<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#fc7f44\" stroke = \"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> 2001- 6000 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#b30000\" stroke = \"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> 6001 - 7200");
    zip2Lyr("../centropais/data/centros_de_mercado_POIC.zip", centrosPOIC, layer_centrosPOIC);
    layerControl.addOverlay(layer_centrosPOIC, "Centros de mercado POIC <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#d1ff73\"   stroke=\"#aaff00\" stroke-dasharray=\" \"></rect></svg> Terciario<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#8e1973\" stroke = \"#a80084\" stroke-dasharray=\" \"></rect></svg> Secundario<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#ff5500\" stroke = \"#e60000\" stroke-dasharray=\" \"></rect></svg> Primario");
    zip2Lyr("../centropais/data/hacia_POIC.zip", haciaPOIC, layer_haciaPOIC);
    layerControl.addOverlay(layer_haciaPOIC, "Número de viajes <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#e3fcd9\"   stroke=\"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> Menos de 500<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#b4d787\" stroke = \"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> 501 - 1000<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#4bc44f\" stroke = \"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> 1001 - 2000 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#218542\" stroke = \"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> 2001 - 4000 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#00451c\" stroke = \"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> 4001 - 10612");
    zip2Lyr("../centropais/data/desde_POIC.zip", desdePOIC, layer_desdePOIC);
    layerControl.addOverlay(layer_desdePOIC, "Número de viajes <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#ffebbf\"   stroke=\"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> Menos de 500<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#ffaa00\" stroke = \"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> 501 - 1000<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#fc7f44\" stroke = \"#6e6e6e\" stroke-dasharray=\" \"></rect></svg> 1001- 2000");
    zip2Lyr("../centropais/data/limite_ZMs.zip", lim_zms, layer_limZMs);
    layerControl.addOverlay(layer_limZMs, "&nbsp; <svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"none\" stroke=\"rgba(168,0,0,1)\" stroke-dasharray=\" \"></rect></svg> Límites de zonas metropolitanas");
    zip2Lyr("../centropais/data/ZMs.zip", zms, layer_ZMs);
    layerControl.addOverlay(layer_ZMs, "&nbsp; <svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"rgba(255,170,0,1)\" stroke=\"rgba(110,100,100,1)\" stroke-dasharray=\" \"></rect></svg>&nbsp;Zonas metropolitanas");
    layerControl.addOverlay(layer_locUrban, "<img src=\"http://gaia.inegi.org.mx/NLB/tunnel/wms/mdm6wms?map=/opt/map/mdm60/mdm61leyendaprueba.map&Request=GetLegendGraphic&format=image/png&Version=1.1.1&Service=WMS&LAYER=c102\" alt=\"Localidades urbanas\"/>");
    layerControl.addOverlay(layer_limiteMunicipal, "<img src=\"http://gaia.inegi.org.mx/NLB/tunnel/wms/wms61?version=1.3.0&service=WMS&request=GetLegendGraphic&sld_version=1.1.0&layer=c101&format=image/png&STYLE=default\" alt=\"Límite municipal\"/>");
    layerControl.addOverlay(layer_limiteEstatal, "Límite estatal <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src=\"http://gaia.inegi.org.mx/NLB/tunnel/wms/wms61?version=1.3.0&service=WMS&request=GetLegendGraphic&sld_version=1.1.0&layer=c100&format=image/png&STYLE=default\" alt=\"Límite Estatal\"/>");


    let resetControl = L.control({
        position: "topleft"
    });

    resetControl.onAdd = () => {
        let div = L.DomUtil.create("div", "leaflet-bar leaflet-control");
        div.innerHTML = "<button type=\"button\" class=\"btn btn-sm btn-light\" id=\"resetFlows\" title=\"Reiniciar fujos\"><i class=\"fa fa-refresh\"></i></button>";
        //div.innerHTML = "<a class=\"btn btn-sm btn-light\" href=\"#\" role=\"button\" id=\"resetFlows\" title=\"Reiniciar fujos\" aria-label=\"aaa\"><i class=\"fa fa-refresh\"></i></a>";
        return div;
    };

    resetControl.addTo(map);

    $.getJSON("data/od.geojson", data => {
        od = data;
    });

    let canvasPointRenderer = L.canvas({ pane: 'pane_flujos' });

    $.getJSON("data/viajes_ocupados_desde.geojson", data => {
        flowMapLayer = L.canvasFlowmapLayer(data, {
            // Define origins and destination from json values
            originAndDestinationFieldIds: {
                originUniqueIdField: "id_orig",
                originGeometry: {
                    x: "xo",
                    y: "yo"
                },
                destinationUniqueIdField: "id_dest",
                destinationGeometry: {
                    x: "xd",
                    y: "yd"
                }
            },
            // Line styles
            canvasBezierStyle: {
                type: "classBreaks",
                field: "viajes",
                classBreakInfos: [{
                    classMinValue: 0,
                    classMaxValue: 1000,
                    symbol: {
                        strokeStyle: "#00c5ff",
                        lineWidth: 0.5,
                        lineCap: "round",
                        shadowColor: "#00c5ff",
                        shadowBlur: 1.5
                    }
                }, {
                    classMinValue: 1001,
                    classMaxValue: 2000,
                    symbol: {
                        strokeStyle: "#008fdc",
                        lineWidth: 1.5,
                        lineCap: "round",
                        shadowColor: "#008fdc",
                        shadowBlur: 1.5
                    }
                }, {
                    classMinValue: 2001,
                    classMaxValue: 6000,
                    symbol: {
                        strokeStyle: "#005ce6",
                        lineWidth: 2,
                        lineCap: "round",
                        shadowColor: "#005ce6",
                        shadowBlur: 1.5
                    }
                }, {
                    classMinValue: 6001,
                    classMaxValue: 7200,
                    symbol: {
                        strokeStyle: "#4c0073",
                        lineWidth: 10,
                        lineCap: "round",
                        shadowColor: "#4c0073",
                        shadowBlur: 1.5
                    }
                }]
            },
            // Animated line styles
            animatedCanvasBezierStyle: {
                type: "classBreaks",
                field: "viajes",
                classBreakInfos: [{
                    classMinValue: 0,
                    classMaxValue: 1000,
                    symbol: {
                        strokeStyle: "#00c5ff",
                        lineWidth: 0.5,
                        lineDashOffsetSize: 4,
                        lineCap: "round",
                        shadowColor: "#00c5ff",
                        shadowBlur: 1.5
                    }
                }, {
                    classMinValue: 1001,
                    classMaxValue: 2000,
                    symbol: {
                        strokeStyle: "#008fdc",
                        lineWidth: 1.5,
                        lineDashOffsetSize: 4,
                        lineCap: "round",
                        shadowColor: "#008fdc",
                        shadowBlur: 1.5
                    }
                }, {
                    classMinValue: 2001,
                    classMaxValue: 6000,
                    symbol: {
                        strokeStyle: "#005ce6",
                        lineWidth: 4,
                        lineDashOffsetSize: 4,
                        lineCap: "round",
                        shadowColor: "#005ce6",
                        shadowBlur: 1.5
                    }
                }, {
                    classMinValue: 6001,
                    classMaxValue: 7200,
                    symbol: {
                        strokeStyle: "#4c0073",
                        lineWidth: 15,
                        lineDashOffsetSize: 4,
                        lineCap: "round",
                        shadowColor: "#4c0073",
                        shadowBlur: 1.5
                    }
                }]
            },
            // dot styles
            style: function (geoJsonFeature) {
                if (geoJsonFeature.properties.isOrigin) {
                    return {
                        renderer: canvasPointRenderer,
                        radius: 5,
                        weight: 1,
                        color: 'rgb(195, 255, 62)',
                        fillColor: 'rgba(195, 255, 62, 0.6)',
                        fillOpacity: 0.6
                    };
                } else {
                    return {
                        renderer: canvasPointRenderer,
                        radius: 2.5,
                        weight: 0.25,
                        color: 'rgb(17, 142, 170)',
                        fillColor: 'rgb(17, 142, 170)',
                        fillOpacity: 0.7
                    };
                }
            },
            // some custom options
            pathDisplayMode: "all",
            animationStarted: true,
            //animationEasingFamily: "Cubic",
            //animationEasingType: "In",
            animationEasingFamily: "Linear",
            animationEasingType: "None",
            animationDuration: 2000,
            pane: "pane_flujos"
        }).bindTooltip( layer => { // what to display on hover
            let coords = layer.getLatLng();
            let label = od.features.filter( f => f.properties.X == coords.lng && f.properties.Y == coords.lat);
            return label[0].properties.CMCP;
        });
        flowMapLayer.addTo(map);
        // hack to get origins and destinations in desired map pane
        //$(".leaflet-pane.leaflet-overlay-pane canvas").detach().appendTo($(".leaflet-pane_flujos-pane"));

        // Define what happens when user clicks dots
        flowMapLayer.on("click", e => {
            // clear paths
            flowMapLayer.clearAllPathSelections();
            let origins = "";
            // select and draw flows from origins
            if (e.sharedOriginFeatures.length) {
                flowMapLayer.selectFeaturesForPathDisplay(e.sharedOriginFeatures, "SELECTION_NEW");
                /*e.sharedOriginFeatures.forEach( origin => {
                    origins += `${origin.properties.muni_origen} &rarr; ${origin.properties.muni_destino}: ${origin.properties.viajes} viajes <br>`;
                });*/
            }
            // select and add flows toward those origins, i.e., for dots that are both origins and destinations
            let dests = flowMapLayer.originAndDestinationGeoJsonPoints.features.filter( f => f.geometry.coordinates[0] === e.latlng.lng && f.geometry.coordinates[1] === e.latlng.lat);
            flowMapLayer.selectFeaturesForPathDisplay(dests, "SELECTION_ADD");
            dests.forEach( dest => {
                //origins += `${dest.properties.muni_origen} &rarr; ${dest.properties.muni_destino}: ${dest.properties.viajes} viajes <br>`;
                origins += `<tr><td>${dest.properties.muni_origen}</td><td>${dest.properties.muni_destino}</td><td>${dest.properties.viajes}</td></tr>`;
            });
            $("#tblViajesDesde tbody").html(origins);

            // if dots are only destinations, add paths when clicked on
            /*if (e.sharedDestinationFeatures.length) {
                flowMapLayer.selectFeaturesForPathDisplay(e.sharedDestinationFeatures, "SELECTION_NEW");
            }*/
        });

        // reset to all flows displayed
        $("#resetFlows").on("click", () => {
            flowMapLayer.selectFeaturesForPathDisplay(flowMapLayer.originAndDestinationGeoJsonPoints.features, "SELECTION_NEW");
            $("#tblViajesDesde tbody").html("");
        });
    });

/*    // Localize Leaflet.Draw texts
    L.drawLocal = {
        draw: {
            toolbar: {
                actions: {
                    title: "Cancelar dibujo",
                    text: "Cancelar"
                },
                finish: {
                    title: "Terminar dibujo",
                    text: "Terminar"
                },
                undo: {
                    title: "Eliminar último punto dibujado",
                    text: "Eliminar último punto"
                },
                buttons: {
                    polyline: "Dibujar una polilínea",
                    polygon: "Dibujar un polígono",
                    rectangle: "Dibujar un rectángulo",
                    circle: "Dibujar un círculo",
                    marker: "Dibujar un marcador",
                    circlemarker: "Dibujar un marcador circular"
                }
            },
            handlers: {
                circle: {
                    tooltip: {
                        start: "Haz click y arrastra para dibujar un círculo"
                    },
                    radius: "Radio"
                },
                circlemarker: {
                    tooltip: {
                        start: "Haz click en el mapa para ubicar el marcador circular"
                    }
                },
                marker: {
                    tooltip: {
                        start: "Haz click en el mapa para ubicar el marcador"
                    }
                },
                polygon: {
                    error: "<strong>Error:</strong>",
                    tooltip: {
                        start: "Haz click para empezar a dibujar la figura",
                        cont: "Haz click para continuar dibujando la figura",
                        end: "Haz click en el primer punto para cerrar la figura"
                    }
                },
                polyline: {
                    error: "<strong>Error:</strong> las líneas no deben cruzarse",
                    tooltip: {
                        start: "Haz click para empezar a dibujar la línea",
                        cont: "Haz click para continuar dibujando la línea",
                        end: "Haz click en el último punto para terminar la línea"
                    }
                },
                rectangle: {
                    tooltip: {
                        start: "Haz click y arrastra para dibujar un rectángulo"
                    }
                },
                simpleshape: {
                    tooltip: {
                        end: "Suelta el ratón para terminar de dibujar"
                    }
                }
            }
        },
        edit: {
            toolbar: {
                actions: {
                    save: {
                        title: "Guardar los cambios",
                        text: "Guardar"
                    },
                    cancel: {
                        title: "Cancelar la edición, descarta todos los cambios",
                        text: "Cancelar"
                    },
                    clearAll: {
                        title: "Limpiar todas las capas",
                        text: "Limpiar todo"
                    }
                },
                buttons: {
                    edit: "Editar capas",
                    editDisabled: "No hay capas que editar",
                    remove: "Eliminar capas",
                    removeDisabled: "No hay capas que eliminar"
                }
            },
            handlers: {
                edit: {
                    tooltip: {
                        text: "Arrastra el marcador para editar la figura",
                        subtext: "Haz click en cancelar para deshacer los cambios"
                    }
                },
                remove: {
                    tooltip: {
                        text: "Haz click en una figura para eliminarla"
                    }
                }
            }
        }
    }
    // leaflet draw control
    drawnItems = L.featureGroup().addTo(map);

    let drawControl = new L.Control.Draw({
        draw: {
            polygon: {
                showArea: true,
                //allowIntersection: false, // Restricts shapes to simple polygons
                //drawError: {
                //color: "#f9a800",
                //message: "<strong>you can't draw that!" // Message that will show when intersect
                //},
                shapeOptions: {
                    color: "#42ffc3"
                }
            },
            // disable toolbar item by setting it to false
            polyline: {
                //allowIntersection:false,
                shapeOptions: {
                    color: "#42ffc3"
                }
            },
            rectangle: {
                shapeOptions: {
                    color: "#42ffc3"
                }
            },
            marker: false,
            circlemarker: false,
            circle: false // Turns off this drawing tool
        },
        edit: {
            featureGroup: drawnItems,
            //remove: false
        }
    });
    map.addControl(drawControl);

    // set z-index of panes so actions can be done on drawnItems when editing/deleting
    map.on(L.Draw.Event.CREATED, event => {
        $("#mexmap .leaflet-pane.leaflet-overlay-pane").css("z-index", "400");
        let layer = event.layer,
            feature = layer.feature = layer.feature || {}; // Initialize feature

        feature.type = feature.type || "Feature"; // Initialize feature.type
        feature.properties = feature.properties || {}; // Initialize feature.properties

        drawnItems.addLayer(layer); // whatever you want to do with the created layer

        // give each drawn item an id and color from an array
        styleDrawnItems();
        // disable buttons if there are 10 drawn items
        toggleButtons();

        // after drawing shape, update chart with data for polygons contained inside it
        updateCharts();
    });

    map.on(L.Draw.Event.DELETESTART, () => {
        // before deleting shape, bring pane up
        $("#mexmap .leaflet-pane.leaflet-overlay-pane").css("z-index", "451");
    });

    map.on(L.Draw.Event.DELETED, () => {
        // after deleting a drawn item, refresh the list of ids and colors
        styleDrawnItems();
        // enable buttons if there are less than 10 drawn items
        toggleButtons();

        // after deleting shape, send pane down
        $("#mexmap .leaflet-pane.leaflet-overlay-pane").css("z-index", "400");
        // and update chart with data:
        // if there are drawnItems, use them. If not, use original data
        updateCharts();
    });

    map.on(L.Draw.Event.EDITSTART, () => {
        $("#mexmap .leaflet-pane.leaflet-overlay-pane").css("z-index", "451");
        // before  editing shape, bring pane up
    });

    map.on(L.Draw.Event.EDITSTOP, () => {
        $("#mexmap .leaflet-pane.leaflet-overlay-pane").css("z-index", "400");
        // before  editing shape, bring pane up
    });

    map.on(L.Draw.Event.EDITED, () => {
        // before  editing shape, send pane down
        $("#mexmap .leaflet-pane.leaflet-overlay-pane").css("z-index", "400");
        // after editing shape, update chart with data for polygons contained inside it
        updateCharts();
    });
    */
}