if (typeof mapControl === 'undefined' || mapControl === null ){
    let titleControl;
    let mapControl;
    let markersLayer;
}
ActivityMapUtil = {

    initMap : function(namespace) {

        const tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                maxZoom: 20,
                attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap.</a>'
            }),
            latlng = L.latLng(22.5, 20);

        mapControl = L.map(namespace + 'map', {center: latlng, zoom: 2, layers: [tiles]});
        markersLayer = L.markerClusterGroup({ chunkedLoading: true, maxClusterRadius: 20, singleMarkerMode: true , showCoverageOnHover: true });
        mapControl.addLayer(markersLayer);

        return mapControl;
    },

    initTitleControl : function(map){

        let TitleControl = L.Control.extend({
            options: {
                // Default control position
                position: 'topleft'
            },
            setPosition: function(position){
                this.options.position = position;
            },
            onAdd: function(map) {
                return L.DomUtil.create('div', 'map-title-control');
            },
            setTitle: function(title){
                this.getContainer().innerHTML = '<strong>' + title + '</strong>'
            }
        });
        titleControl = new TitleControl().addTo(map);
        return titleControl;
    },

    updateMarkers: function (map, jsonData){


        if (jsonData != null && jsonData !== "") {
            const locations = JSON.parse(jsonData);
            locations.map((location, i) => {
                const label = location.city;
                const position = location.position;
                let contentString = '<div>'
                    + '<strong>City: ' + label + '</strong>';

                let products = location.products;
                if (products.length > 0) {
                    contentString += '<table><tr><th>Download</th><th>Count</th></tr>';
                    products.forEach(function (product) {
                        contentString += '<tr><td>' + product.downloadName + '</td><td>' + product.downloadCount + '</td></tr>';
                    });
                    contentString += '</table>';
                } else {
                    contentString += '<p>User login</p>'
                }
                contentString += '</div>';

                const marker = L.marker(L.latLng(position.lat, position.lng, {title: label}));
                marker.bindPopup(contentString);
                markersLayer.addLayer(marker);

            });
        }
    },

    getRunningProcess: function (namespace){
        let runningProcess = document.getElementById(namespace + "runningProcess");
        return runningProcess.value;
    },

    setRunningProcess: function (namespace, processId){
        let runningProcess = document.getElementById(namespace + "runningProcess");
        runningProcess.value = processId;
    },

    stopRunningProcess : function (namespace){
        clearInterval(this.getRunningProcess(namespace));
        this.setRunningProcess(namespace, undefined);
    },

    startDownloadActivityMap :  function (resourceUrl, namespace){

        let map  = ActivityMapUtil.initMap(namespace);
        let titleControl = ActivityMapUtil.initTitleControl(map);
        titleControl.setTitle("Loading map data... Progress 0 %");

        let A = new AUI();
        A.io.request(resourceUrl + '&' + namespace + 'action=start', {
            sync : 'true',
            cache : 'false',
            on : {
                success : function(response, status, xhr) {
                    if (xhr.status === 200){
                        let responseData = this.get('responseData');
                        ActivityMapUtil.updateMarkers(namespace, responseData);
                        titleControl.setTitle("");
                    } else if (xhr.status === 204){
                        //Data not loaded yet so start download process
                        ActivityMapUtil.setRunningProcess(namespace, setInterval(function () {
                            ActivityMapUtil.statusDownloadActivityMap(resourceUrl, namespace);
                        }, 1000));

                    }
                }
            }
        });
    },

    downloadDownloadActivityMap :  function (resourceUrl, namespace){

        ActivityMapUtil.stopRunningProcess(namespace);

        let A = new AUI();
        A.io.request(resourceUrl + '&' + namespace + 'action=download', {
            sync : 'true',
            cache : 'false',
            on : {
                success : function(response, status, xhr) {
                    if (xhr.status === 200){
                        let responseData = this.get('responseData');
                        ActivityMapUtil.updateMarkers(namespace, responseData);
                        titleControl.setTitle("");
                    }
                }
            }
        });
    },

    statusDownloadActivityMap : function (resourceUrl, namespace){

        let A = new AUI();
        A.io.request(resourceUrl + '&' + namespace + 'action=updateStatus', {
            sync : 'true',
            cache : 'false',
            on : {
                success : function(response, status, xhr) {
                     if (xhr.status === 200){
                        let responseData = this.get('responseData');

                        let statusMsg = JSON.parse(responseData);
                        if (statusMsg.status === 'available') {
                            ActivityMapUtil.downloadDownloadActivityMap(resourceUrl, namespace);
                        } else if (statusMsg.status === 'running') {
                            let percent = 100 * statusMsg.progress / statusMsg.total;
                            titleControl.setTitle('Loading map data... Progress ' + Math.round(percent) + ' %');
                        } else {
                            ActivityMapUtil.stopRunningProcess(namespace);
                        }

                    } else {
                         ActivityMapUtil.stopRunningProcess(namespace);
                    }
                },
                error : function (){
                    ActivityMapUtil.stopRunningProcess(namespace);
                },
                failure : function(response, status, xhr) {
                    ActivityMapUtil.stopRunningProcess(namespace);
                }
            }
        });

    }

}

UserPortraitUtil = {

    updateTitle: function (namespace, title){
        let userPortraits = document.getElementById(namespace + "title");
        userPortraits.innerHTML = title;
    },

    updatePortraits: function (namespace, jsonData){

        if (jsonData != null && jsonData !== "") {
            const urls = JSON.parse(jsonData);
            let contents = [];
            urls.map((url, i) => {

                if (i === 0){
                    contents.push('<div class="carousel-item col-12 col-sm-6 col-md-4 col-lg-3 active">');
                } else {
                    contents.push('<div class="carousel-item col-12 col-sm-6 col-md-4 col-lg-3">');
                }
                contents.push('<img src="' + url + '" alt="img'+ i + '" class="img-fluid mx-auto d-block">')
                contents.push('</div>')
            });
            let userPortraits = document.getElementById(namespace + "portraits");
            userPortraits.innerHTML = contents.join("");
        }
        this.addCarouselSlider();
    },

    addCarouselSlider: function (){

        $('#user-portraits-carousel').on('slide.bs.carousel', function(e) {
            var $e = $(e.relatedTarget);
            let idx = $e.index();
            let itemsPerSide = 5;
            let totalItems = $('.carousel-item').length;
            if (idx >= itemsPerSide - (totalItems - idx) ){
                let it = itemsPerSide - (totalItems - idx);
                for (let i=0; i < it; i++){
                    // append slides to end
                    if (e.direction === "left") {
                        $('.carousel-item').eq(i).appendTo('.carousel-inner');
                    }
                    else {
                        $('.carousel-item').eq(0).appendTo('.carousel-inner');
                    }
                }
            }

        });

    },
    getRunningProcess: function (namespace){
        let runningProcess = document.getElementById(namespace + "runningProcess");
        return runningProcess.value;
    },

    setRunningProcess: function (namespace, processId){
        let runningProcess = document.getElementById(namespace + "runningProcess");
        runningProcess.value = processId;
    },

    stopRunningProcess : function (namespace){
        clearInterval(this.getRunningProcess(namespace));
        this.setRunningProcess(namespace, undefined);
    },

    startUserPortraits :  function (resourceUrl, namespace){

        UserPortraitUtil.updateTitle(namespace, "Loading user portraits... Progress 0 %");

        let A = new AUI();
        A.io.request(resourceUrl + '&' + namespace + 'action=start', {
            sync : 'true',
            cache : 'false',
            on : {
                success : function(response, status, xhr) {
                    if (xhr.status === 200){
                        let responseData = this.get('responseData');
                        UserPortraitUtil.updatePortraits(namespace, responseData);
                        UserPortraitUtil.updateTitle("");
                    } else if (xhr.status === 204){
                        //Data not loaded yet so start download process
                        UserPortraitUtil.setRunningProcess(namespace, setInterval(function () {
                            UserPortraitUtil.statusUserPortraits(resourceUrl, namespace);
                        }, 1000));

                    }
                }
            }
        });
    },

    downloadUserPortraits :  function (resourceUrl, namespace){

        UserPortraitUtil.stopRunningProcess(namespace);

        let A = new AUI();
        A.io.request(resourceUrl + '&' + namespace + 'action=download', {
            sync : 'true',
            cache : 'false',
            on : {
                success : function(response, status, xhr) {
                    if (xhr.status === 200){
                        let responseData = this.get('responseData');
                        UserPortraitUtil.updatePortraits(namespace, responseData);
                        UserPortraitUtil.updateTitle(namespace, "");
                    }
                }
            }
        });
    },

    statusUserPortraits : function (resourceUrl, namespace){

        let A = new AUI();
        A.io.request(resourceUrl + '&' + namespace + 'action=updateStatus', {
            sync : 'true',
            cache : 'false',
            on : {
                success : function(response, status, xhr) {
                     if (xhr.status === 200){
                        let responseData = this.get('responseData');

                        let statusMsg = JSON.parse(responseData);
                        if (statusMsg.status === 'available') {
                            UserPortraitUtil.downloadUserPortraits(resourceUrl, namespace);
                        } else if (statusMsg.status === 'running') {
                            let percent = 100 * statusMsg.progress / statusMsg.total;
                            UserPortraitUtil.updateTitle(namespace, 'Loading user portraits... Progress ' + Math.round(percent) + ' %');
                        } else {
                            UserPortraitUtil.stopRunningProcess(namespace);
                        }

                    } else {
                         UserPortraitUtil.stopRunningProcess(namespace);
                    }
                },
                error : function (){
                    UserPortraitUtil.stopRunningProcess(namespace);
                },
                failure : function(response, status, xhr) {
                    UserPortraitUtil.stopRunningProcess(namespace);
                }
            }
        });

    }

}

